为什么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需要打开才能访问我的MemoryStream

默认情况下,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);
        }