通过StreamWriter写入MemoryStream时缓冲区出现空字节问题
问题原因与解决方案
首先你原代码里有个明显的错误:StreamWriter的构造函数没传入目标MemoryStream,这会导致你的写入根本没到stream里,修正后的基础代码应该是这样:
using (MemoryStream stream = new MemoryStream()) { using (StreamWriter writer = new StreamWriter(stream)) // 必须传入目标stream { writer.WriteLine("SELECT"); writer.WriteLine(" T.*"); writer.WriteLine("FROM"); writer.WriteLine(" [A Table] T"); writer.WriteLine("WHERE"); writer.WriteLine($" T.[Data Field] IN ({data})"); } // 原代码的问题出在GetBuffer()的使用上 return new MemoryStream(stream.GetBuffer()); }
你遇到的末尾额外0字节,是因为MemoryStream.GetBuffer()返回的是它整个底层缓冲区(默认初始大小为256字节),哪怕你只写入了几十字节,缓冲区未被使用的部分就会填充0。而你后来用Encoding.UTF8.GetBytes()的方式,是直接生成刚好容纳字符串内容的字节数组,自然不会有多余字节。
要保留StreamWriter的用法同时解决这个问题,有两个简单可行的办法:
方法一:使用MemoryStream.ToArray()
ToArray()会仅返回实际写入的字节内容,完全避开底层缓冲区的多余部分,这是最推荐的方式:
using (MemoryStream stream = new MemoryStream()) { using (StreamWriter writer = new StreamWriter(stream)) { writer.WriteLine("SELECT"); writer.WriteLine(" T.*"); writer.WriteLine("FROM"); writer.WriteLine(" [A Table] T"); writer.WriteLine("WHERE"); writer.WriteLine($" T.[Data Field] IN ({data})"); } return new MemoryStream(stream.ToArray()); }
方法二:指定GetBuffer()的有效长度
如果你一定要使用GetBuffer(),可以在创建新MemoryStream时,仅截取实际写入的字节范围:
using (MemoryStream stream = new MemoryStream()) { using (StreamWriter writer = new StreamWriter(stream)) { writer.WriteLine("SELECT"); writer.WriteLine(" T.*"); writer.WriteLine("FROM"); writer.WriteLine(" [A Table] T"); writer.WriteLine("WHERE"); writer.WriteLine($" T.[Data Field] IN ({data})"); } // 只取从0到stream.Length的有效字节部分 return new MemoryStream(stream.GetBuffer(), 0, (int)stream.Length); }
补充说明:StreamWriter的using块结束时会自动调用Flush()并关闭写入流,但不会关闭底层的MemoryStream,所以后续操作stream是完全没问题的。
内容的提问来源于stack exchange,提问作者Emma Harris
相关产品推荐
相关产品推荐

