为什么需要打开 StreamWriter 才能访问我的 MemoryStream?
Why does StreamWriter need to be open to access my MemoryStream?
我有一些测试代码正在准备 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
对象,据我所知,它绝对应该被处理。
如果我已经将其内容刷新到 MemoryStream
对象,为什么 StreamWriter
需要保持打开状态?
我可以想出一些非常不方便的方法来解决这个问题,但我想知道为什么它不能按照我想要的方式工作,以及我是否可以做些什么来让它工作那样。感谢任何建议,谢谢!
using
运算符在退出运算符块 { }
.
之前调用对象的 Dispose
方法
在处置时,StreamWriter
也处置标的 Stream
。
这意味着您的 Stream
在得到 returned 之前是一个无效的对象。
仅对在当前范围内创建和销毁的对象应用 using
语句(至少不要 return 它们)。
Why does the StreamWriter need to remain open if I've flushed its
contents to the MemoryStream object already?
如@mikez 所述,默认情况下创建 StreamWriter
"owns" 底层流,但您可以通过在构造函数中添加 leaveOpen = true
来避免此行为。
new StreamWriter(stream = s, encoding = Encoding.UTF8, bufferSize = 128, leaveOpen = true)
默认情况下,StreamWriter
"owns" 流被传递并在处理时关闭它。使用具有 leaveOpen
boolean parameter 的构造函数。将其设置为 true 以避免在第一个示例中处理编写器时关闭基础 Stream
。
StreamWriter
会自动关闭 Stream
如果你不告诉它不要。像这样创建它而不是让 Stream
打开:
using (var writer = new StreamWriter(stream, System.Text.Encoding.UTF8, 1024, true))
或者,如果您不想传递额外的参数,请使用 GetBuffer
访问 MemoryStream
的内部缓冲区。避免 ToArray
,因为这会创建数据副本,并且根据您的情况可能效率低下。
其他答案表明我应该使用具有 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);
}
我有一些测试代码正在准备 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
对象,据我所知,它绝对应该被处理。
如果我已经将其内容刷新到 MemoryStream
对象,为什么 StreamWriter
需要保持打开状态?
我可以想出一些非常不方便的方法来解决这个问题,但我想知道为什么它不能按照我想要的方式工作,以及我是否可以做些什么来让它工作那样。感谢任何建议,谢谢!
using
运算符在退出运算符块 { }
.
Dispose
方法
在处置时,StreamWriter
也处置标的 Stream
。
这意味着您的 Stream
在得到 returned 之前是一个无效的对象。
仅对在当前范围内创建和销毁的对象应用 using
语句(至少不要 return 它们)。
Why does the StreamWriter need to remain open if I've flushed its contents to the MemoryStream object already?
如@mikez 所述,默认情况下创建 StreamWriter
"owns" 底层流,但您可以通过在构造函数中添加 leaveOpen = true
来避免此行为。
new StreamWriter(stream = s, encoding = Encoding.UTF8, bufferSize = 128, leaveOpen = true)
默认情况下,StreamWriter
"owns" 流被传递并在处理时关闭它。使用具有 leaveOpen
boolean parameter 的构造函数。将其设置为 true 以避免在第一个示例中处理编写器时关闭基础 Stream
。
StreamWriter
会自动关闭 Stream
如果你不告诉它不要。像这样创建它而不是让 Stream
打开:
using (var writer = new StreamWriter(stream, System.Text.Encoding.UTF8, 1024, true))
或者,如果您不想传递额外的参数,请使用 GetBuffer
访问 MemoryStream
的内部缓冲区。避免 ToArray
,因为这会创建数据副本,并且根据您的情况可能效率低下。
其他答案表明我应该使用具有 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);
}