为什么StreamWriter需要打开才能访问我的MemoryStream
本文关键字:访问 我的 MemoryStream StreamWriter 为什么 | 更新日期: 2023-09-27 18:21:44
我有一些测试代码正在准备一个MemoryStream
,它最终将被对象读取。以下是我希望如何编写它:
var manager = new LeaderboardImportManager(leaderboard);
var columnNames = manager.ColumnNames;
var stream = new MemoryStream();
using (var writer = new StreamWriter(stream))
{
writer.WriteLine(string.Join(",", columnNames));
foreach (var user in users)
{
var row = leaderboard.Metrics.Select(m => Faker.RandomNumber.Next().ToString()).ToList();
row.Insert(0, user.UserName);
writer.WriteLine(string.Join(",", row));
}
writer.Flush();
stream.Position = 0;
}
return stream;
但当我这样做的时候,我的流对象变得不可读,我的测试失败了,所以我必须这样做:
var manager = new LeaderboardImportManager(leaderboard);
var columnNames = manager.ColumnNames;
var stream = new MemoryStream();
var writer = new StreamWriter(stream);
writer.WriteLine(string.Join(",", columnNames));
foreach (var user in users)
{
var row = leaderboard.Metrics.Select(m => Faker.RandomNumber.Next().ToString()).ToList();
row.Insert(0, user.UserName);
writer.WriteLine(string.Join(",", row));
}
writer.Flush();
stream.Position = 0;
return stream;
当然,这使我无法处理我的StreamWriter
对象,据我所知,它肯定应该被处理。
如果我已经将StreamWriter
的内容刷新到MemoryStream
对象,为什么CCD_3需要保持打开状态?
我可以想出一些非常不方便的方法来解决这个问题,但我想知道为什么它不能按照我想要的方式工作,以及我是否可以做些什么来让它以这种方式工作。任何建议都将不胜感激,谢谢!
默认情况下,StreamWriter
"拥有"它所传递的流,并将在处理时关闭它。使用具有leaveOpen
布尔参数的构造函数。将其设置为true,以避免在第一个示例中释放编写器时关闭底层Stream
。
StreamWriter
会自动关闭Stream
,如果你不告诉它不要这样做的话
using (var writer = new StreamWriter(stream, System.Text.Encoding.UTF8, 1024, true))
或者,如果不希望传递额外的参数,可以使用GetBuffer
访问MemoryStream
的内部缓冲区。避免ToArray
,因为这会创建数据的副本,并且根据您的情况可能效率低下。
using
运算符在退出运算符块{ }
之前调用对象上的Dispose
方法。
在处置时,StreamWriter
也处置底层Stream
。
这意味着您的Stream
在返回之前是一个无效对象。
仅对在当前作用域中创建和销毁的对象应用using
语句(至少不要返回它们)。
如果我刷新了StreamWriter的MemoryStream对象的内容?
正如@mikez所提到的,默认情况下创建的StreamWriter
"拥有"底层流,但您可以通过在构造函数中添加leaveOpen = true
来避免这种行为。
new StreamWriter(stream = s, encoding = Encoding.UTF8, bufferSize = 128, leaveOpen = true)
其他答案表明我应该使用具有leaveOpen
参数的构造函数并将其设置为true,但我不喜欢这样,因为该构造函数还需要bufferSize
参数。
然而,我意识到我可以很容易地逃脱惩罚:
// new method body, returns byte array
var stream = new MemoryStream();
using (var writer = new StreamWriter(stream))
{
writer.WriteLine(string.Join(",", columnNames));
foreach (var user in users)
{
var row = leaderboard.Metrics.Select(m => Faker.RandomNumber.Next().ToString()).ToList();
row.Insert(0, user.UserName);
writer.WriteLine(string.Join(",", row));
}
writer.Flush();
stream.Position = 0;
}
return stream.ToArray();
// consumer opens a new stream using the bytes
using (var stream = new MemoryStream(this.GetCSVStream(leaderboard, users)))
{
mockFile.Setup(f => f.InputStream).Returns(stream);
this.service.UpdateEntries(update.ID, mockFile.Object);
}