我在使用StreamReader读取文件的.NET应用程序中编写文件解析器。要解析的文件以以"<eoh>"
结尾的标头开头。我想要从头开始读取或忽略所有内容。实际数据在此之后开始。
该文件不是基于行的。所有东西都只有这样的标记字符串才能显示。所以我不能使用ReadLine。
如果不一次读取一个字符并实现状态机来识别标记工作字符,我该怎么做?我特意寻找StreamReader.SkipUntilAfter(string)
或StreamReader.ReadUntil(string)
等方法。
哦,这个项目仍在使用.NET 2.0,所以这里不需要LINQ。如果有人建议使用它,我可能会解决这个问题。
答案 0 :(得分:1)
TextReader
一般做已经逐字逐句阅读。他们使用缓冲区以便更快,但StreamReader
的缓冲区与仅提前读取并仅拉到<eoh>
之间没有任何区别。出于同样的原因,在该标题之后也没有更好的方法可以跳过。绝对最佳情况是内置函数,它只是直观地抽象底层代码,因此不是特别有用。
如果你因为某种原因不相信我,here's the source code。
此外,值得注意的是,无论什么,您都必须逐个字符地查看。即使你有办法将它们拉入内存而不这样做,比较两个string
是一个逐字符操作。所以你不会保存任何东西。
就个人而言,我只是喜欢这样的事情。它需要TextReader
和标题结束字符串,并通过reader
读取,直到找到eoh
。然后,它返回bool
是否找到了标记。
public bool SkipUntilAfterHeader(TextReader reader, string eoh)
{
int eohGuessIndex = 0;
int next;
while ((next = reader.Read()) != -1)
{
char c = (char)next;
if (c == eoh[eohGuessIndex])
{
eohGuessIndex++;
if (eohGuessIndex == eoh.Length)
{
return true;
}
}
else
{
eohGuessIndex = 0;
}
}
return false;
}
我不确定.NET 2.0有没有,所以我从头开始写了一些可能有或没有的东西。但性能不应受此影响。这方面的一个不错的方面是,您还可以轻松添加StringBuilder
out
参数,该参数将传递标题信息,以防您以后想要这样做。
然后,使用非常简单。
public void ReadFile(string path)
{
using (StreamReader reader = new StreamReader(path))
{
if (SkipUntilAfterHeader(reader, "<eoh>"))
{
// read file
}
else
{
// corrupt file
}
}
}
但实际上,读取整个文件并返回相关部分可能更容易。与可读性相比,它只取决于性能的重要程度。
在经典不好的形式中,请注意我没有测试 - 甚至编译 - 任何此类。但它应该相对容易修复,即使它不起作用。