C#如何记录StreamReader处理位置并直接跳转至该位置
基于文件物理位置实现断点续读方案
核心逻辑
直接借助StreamReader底层的BaseStream获取文件的字节偏移位置,但要注意StreamReader存在内部缓冲区,直接读取BaseStream.Position会和实际处理进度不一致,必须先清空缓冲区再记录位置。
具体实现步骤
- 记录断点:需要保存处理位置时,先调用
StreamReader.DiscardBufferedData()清空内部缓冲区,再读取streamReader.BaseStream.Position得到当前物理字节位置,将该值存入配置文件或本地存储。 - 恢复断点:下次启动程序时,读取保存的位置值,创建
FileStream并设置其Position为该值,再基于此FileStream实例化StreamReader,即可直接从上次中断的位置开始读取。
代码示例
记录断点位置
using (var streamReader = new StreamReader("data.txt", Encoding.UTF8)) { string line; while ((line = streamReader.ReadLine()) != null) { // 处理当前行的业务逻辑 Console.WriteLine($"处理行:{line}"); // 按需触发断点保存(比如每处理100行或捕获异常时) streamReader.DiscardBufferedData(); long currentPos = streamReader.BaseStream.Position; File.WriteAllText("breakpoint.txt", currentPos.ToString()); } }
从断点恢复读取
long resumePos = 0; if (File.Exists("breakpoint.txt")) { long.TryParse(File.ReadAllText("breakpoint.txt"), out resumePos); } using (var fileStream = new FileStream("data.txt", FileMode.Open, FileAccess.Read)) { fileStream.Position = resumePos; using (var streamReader = new StreamReader(fileStream, Encoding.UTF8)) { string line; while ((line = streamReader.ReadLine()) != null) { // 从断点位置继续处理行 Console.WriteLine($"续处理行:{line}"); } } }
关键注意事项
- 编码一致性:创建
StreamReader时必须指定相同编码(如Encoding.UTF8),否则字节位置会对应错误的字符偏移,导致读取内容错乱。 - 文件不可修改:断点记录后,目标文件不能被修改(新增、删除内容),否则恢复后的读取位置会失效。
- 缓冲区必须清空:只有调用
DiscardBufferedData()后,BaseStream.Position才会指向当前处理行的末尾位置,而非缓冲区已预读的字节位置。
内容的提问来源于stack exchange,提问作者Benny Ae
相关产品推荐
相关产品推荐

