我有一个读取文件方法,它从文件的开头读取日期,然后读取文件末尾的日期。问题是文件很大,需要很长时间。有没有办法我可以读取第一行,忽略除最后一行之外的所有行,然后读取最后一行?
//Time consuming current method
int counter = 0;
DateTime begDate = new DateTime();
DateTime endDate = new DateTime();
while ((read = s.ReadLine()) != null)
{
if (counter != 0) //skip first line
{
string[] Currentline = read.Split(comma);
DateTime ThisBarsDate = DateTime.ParseExact(Currentline[1] + Currentline[2], "yyyyMMddHHmmss", new CultureInfo("en-US"));
if (counter == 1) begDate = ThisBarsDate;
endDate = ThisBarsDate; //will be correct at end of loop
}
counter++;
}
s.Close();
答案 0 :(得分:3)
如果你有一个FileStream,你可以使用Seek方法寻找文件末尾的偏移量并从那里开始阅读。
var file = new FileStream(...);
var reader = new StreamReader(file);
long bytesToSkip = ...number of bytes in last line...
file.Seek( bytesToSkip, SeekOrigin.End );
var endDate = reader.ReadToEnd();
显然,这不是一个完整的解决方案,但它应该足以让你开始。本质上,你想要寻找到文件的末尾 - 这应该跳过文件中除了最后一个之外的所有块,它必须读取才能到达末尾,然后向后导航一些字节。该数字应足以覆盖最后一行。如果你知道它的确切长度,那就更好了。这是我展示的例子。如果没有,请跳过,以确保您已经回到最后一行的开头,然后开始阅读行并进行转换。
答案 1 :(得分:3)
通过现有的API没有固有的简单方法。但是,一种选择是寻找文件的末尾,然后开始向后寻找第一个新的线对。
这是一个快速示例。它不是一个非常强大的解决方案,但它提供了您正在寻找的基本框架。
public string GetLastLine(Stream stream, Encoding enc) {
const int64 range = 100;
var found = false;
var index = stream.Length;
var data = new byte[range];
var builder = new StringBuilder();
while ( true ) {
index = Math.Max(0, index -= range);
var count = stream.Read(data, 0, data.Length);
if ( count == 0 ) {
break;
}
var text = enc.GetString(data, 0, count);
var newLineIndex = text.Index(Environment.NewLine);
if ( newLineIndex >= 0 ) {
builder.Insert(text.SubString(newLineIndex+Environment.NewLine.Length),0);
break;
} else {
builder.Insert(text, 0);
}
}
return builder.ToString();
}
答案 2 :(得分:2)
使用SeekOrigin
的{{1}}查看FileStream.Seek()
。
答案 3 :(得分:2)
请参阅此相关的stackoverflow问题:
答案 4 :(得分:2)
正如其他人所说,没有好的,简单的,内置的方法来做到这一点。您甚至可能需要小心寻找文件的末尾并向后计数,以防可能存在多字节字符。
然而,你仍然可以显着改善。您当前代码的问题在于,它需要时间来解析每个行,即使您只关心第一个和最后一个。试试这个:
//Time consuming current method
DateTime begDate = new DateTime();
DateTime endDate = new DateTime();
s.ReadLine(); //skip first line - assume there is at least the header and the first record
string[] record = s.ReadLine().Split(comma);
begDate = DateTime.ParseExact(record[1] + record[2], "yyyyMMddHHmmss", new CultureInfo("en-US"));
string prev, read;
while ((read = s.ReadLine()) != null)
{
prev = read;
}
record = prev.Split(comma);
endDate = DateTime.ParseExact(record[1] + record[2], "yyyyMMddHHmmss", new CultureInfo("en-US"));
请注意,循环几乎不起作用;它只是复制一个参考。另请注意,我没有显示.Close()
电话。这是因为您使用using
语句打开文件以确保文件已关闭,即使抛出异常也是如此。您确实使用using
语句打开了文件,对吗?
答案 5 :(得分:-3)
以下是您可以用来获取最后一行的代码
StreamReader streamReader = new StreamReader("C:\\Text.txt");
ArrayList lines = new ArrayList();
string t =streamReader.ReadToEnd() ;
streamReader.Close();
Console.Write((t.Substring(t.LastIndexOf(System.Environment.NewLine))));
Console.ReadKey();
希望这会有所帮助。