MemoryStream写入文件为空问题排查:乘客数据写入后复制到文件失败
咱们来一步步拆解为什么你的database.dat文件是空的——核心问题出在流的位置指针上!
当你调用WriteToStream往MemoryStream里写完100条乘客数据后,流的当前位置(Position属性)已经跑到了所有数据的末尾。这时候直接调用CopyFromStream去读这个流,相当于你打开一本书直接翻到最后一页,自然看不到前面的内容,循环条件sr.BaseStream.Position < sr.BaseStream.Length直接不成立,所以什么都没写入文件。
除此之外,你的代码还有两个小隐患:
- 没有用
using语句管理StreamWriter和StreamReader,可能导致资源没正确释放,甚至数据没完全刷入流中; - 依赖
Position判断是否读完流的方式不够可靠,不如直接判断ReadLine()的返回值。
修正方案
我们分三步解决问题:
1. 重置流的位置指针
在写完MemoryStream后,把指针移回到流的开头,这样读取操作才能从第一条数据开始。你可以选择在Main函数里处理:
MemoryStream ms = new(); StreamService.WriteToStream(ms); // 把流的位置重置到开头 ms.Position = 0; StreamService.CopyFromStream(ms, "database.dat");
或者在CopyFromStream方法内部判断并重置(更通用,适合所有支持Seek的流):
public static void CopyFromStream(Stream stream, string filename) { // 如果流支持定位,就把指针移到开头 if (stream.CanSeek) { stream.Seek(0, SeekOrigin.Begin); } // ... 后续代码 }
2. 使用using语句管理流资源
StreamWriter和StreamReader都是实现了IDisposable的类型,用using包裹它们可以自动完成Flush(刷入数据)和Dispose(释放资源)的操作,避免数据丢失:
public static void WriteToStream(Stream stream) { Random rnd = new(); // leaveOpen设为true,避免关闭传入的MemoryStream(咱们还要用它来读数据) using StreamWriter sw = new(stream, leaveOpen: true); for (int i = 0; i < 100; i++) { sw.WriteLine(i); sw.WriteLine($"Passanger{i}"); sw.WriteLine(rnd.Next(0, 2) == 1); } // 显式Flush确保所有数据都写入流中 sw.Flush(); }
public static void CopyFromStream(Stream stream, string filename) { if (stream.CanSeek) { stream.Seek(0, SeekOrigin.Begin); } using StreamReader sr = new(stream); // 用using管理文件写入流,自动关闭文件 using StreamWriter sw = new(File.Open(filename, FileMode.OpenOrCreate)); string line; // 用ReadLine()返回null判断流是否结束,比判断Position更可靠 while ((line = sr.ReadLine()) != null) { sw.WriteLine(line); } // 不需要手动调用sw.Close(),using会自动处理 }
3. 优化读取逻辑
原来的while (sr.BaseStream.Position < sr.BaseStream.Length)判断方式有漏洞:比如当流的Position还没到末尾,但ReadLine()已经读到了流结束(返回null),这时候循环会继续执行,导致写入空行。改用while ((line = sr.ReadLine()) != null)是更稳妥的方式,直接判断是否还有可读内容。
修正后的完整流程
MemoryStream被创建,初始位置为0;WriteToStream往流里写入数据,写完后通过using自动Flush,流的位置到了数据末尾;- 重置流的位置到0;
CopyFromStream从流的开头读取每一行数据,写入到database.dat文件;- 所有流资源通过
using自动释放,数据完整保存到文件中。
内容的提问来源于stack exchange,提问作者Hleb Butkevich

