是否有一个类允许您在C#中按行号读取行?
我了解StreamReader和TextFieldParser,但AFAIK不具备此功能。例如,如果我知道我的文本文件中的行号34572包含某些数据,那么不必调用StreamReader.ReadLine()
34572次就可以了。
答案 0 :(得分:9)
除非文件具有精确且预先确定的格式,例如每条线具有相同的长度,否则无法在文本文件中进行搜索。
为了找到i th 行,您必须找到第一个i-1行结束。如果您对这些行结束的位置一无所知,那么您必须读取整个文件,直到i th 行。
答案 1 :(得分:5)
这不是C#的问题 - 这是行终止符的问题。没有办法跳到34572行,因为你不知道它何时开始 - 你唯一知道的是它在找到34571 \r\n
之后开始。如果您需要此功能,则根本不想使用文本文件:)
一种简单(但仍然很慢)的方法是使用File.ReadLines(...)
:
var line = File.ReadLines(fileName).Skip(34571).FirstOrDefault();
然而,最好的方法是知道线的实际字节偏移量。如果您记住偏移量而不是行号,则可以简单地在流中搜索并避免读取不必要的数据。然后你就像往常一样继续阅读这条线:
streamReader.BaseStream.Seek(offset, SeekOrigin.Begin);
var line = streamReader.ReadLine();
如果文件仅附加(例如日志文件)并且您可以记住书签,这将非常有用。但是,只有在书签前没有修改文件时,它才会起作用。
总而言之,有三种选择:
byte
缓冲区就可以了。 / LI>
当性能很重要时,文本格式不是首选的原因 - 当您使用用户可编辑的通用文本格式时,第三个选项是唯一选项。因此,从JSON,XML,文本日志文件等中读取将始终意味着至少读取您想要的行。
答案 2 :(得分:0)
这可能不是你的情况,但是如果你知道每一行的长度,你将计算你寻找的行的起始索引字节,可能如下所示:
FileStream fs = new FileStream("fullFileName");
fs.Seek(startByte, SeekOrigin.Current)
for (long offset = startByte; offset < fs.Length; offset++)
{
fs.Seek(-1, SeekOrigin.Current);
char value = (char)((byte)fs.ReadByte());
.
.
.
//To determine the end of each line you can use the conditions below
if (value == 0xA)// hex \n
{
if (offset == fs.Length)
continue;
}
else if (value == 0xD)// hex \r
{
if (offset == fs.Length - 1)
continue;
}
}