我有一个由streamreader读取的文件流 . 我想在IOException事件中将流的位置返回到前一行,以尝试再次读取同一行 . 我试图在行之前记录流的位置,然后寻求到那一点,但我必须误解或误用它 .
using (var fs = new FileStream("MyPath\\linetest.txt", FileMode.Open))
using (var sr = new StreamReader(fs))
{
Console.WriteLine(fs.CanSeek);
while (!sr.EndOfStream)
{
string line;
try
{
var streamPosition = fs.Position;
line = sr.ReadLine();
if (line.StartsWith("#"))
{
fs.Seek(streamPosition, SeekOrigin.Begin);
throw new IOException();
}
Console.WriteLine(line);
}
catch (IOException e)
{
Console.WriteLine(e.Message);
}
}
如果它不明显,我会在读取以“#”开头的行时抛出异常 . 我的7行测试文件中只有一行以#开头,所以我希望该行以无限循环写入,但是,当我执行此行时,它会打印文件的每一行,用异常消息替换该行 . 以 . . 开始 # . 任何洞察力或帮助你的家伙和女孩可以提供的将不胜感激!
1 回答
您的代码进入输入文件末尾的原因是
fs.Position
占据的位置是StreamReader在该阶段(位置A)从FileStream读取到 StreamReader's buffer 的位置 . 这与StreamReader通过sr.ReadLine()
(位置B)返回行的位置不同 . 当然,位置A总是领先于位置B.StreamReader没有提供位置B的方法 . 通过累计计算ReadLine()每次返回的内容来获取这样的物理位置并不是不可能的,但要考虑各种编码和EOL和BOM代码 . 那要准确起来并不容易 .
相反,为什么在StreamReader解码后你没有获得逻辑位置?我的意思是,在这种情况下保留行号 .
catch块中的
sr.DiscardBufferedData()
用于清除我在开头提到的StreamReader中的缓冲区 . 请记住sr.DiscardBufferedData()
会降低性能,这在here中提到 .我不明白你为什么要保持文件流打开并继续获得相同的错误结果 . 请注意,在流打开时,程序永远不会对文件进行更新 . 因此,我再留下一个代码,这些代码可以继续读取相同的行直到修正行,前提是已经处理过的行永远不会在换行符方面进行编辑 .
但是,无论哪种方式,即使您关注性能,从开头到错误行的重复读取也不是那么好 . 在这种情况下,您应该重新考虑设计输入数据的方式 .