【问题标题】:Writing to MemoryStream with StreamWriter returns empty使用 StreamWriter 写入 MemoryStream 返回空
【发布时间】:2011-08-04 21:51:12
【问题描述】:

我不确定自己做错了什么,看过很多例子,但似乎无法正常工作。

public static Stream Foo()
{
    var memStream = new MemoryStream();
    var streamWriter = new StreamWriter(memStream);

    for (int i = 0; i < 6; i++)
        streamWriter.WriteLine("TEST");

    memStream.Seek(0, SeekOrigin.Begin);
    return memStream;
}

我正在对这个方法做一个简单的测试,试图让它通过,但无论如何,我的收集计数是 0。

[Test]
public void TestStreamRowCount()
{
    var stream = Foo();

    using (var reader = new StreamReader(stream))
    {
        var collection = new List<string>();
        string input;

        while ((input = reader.ReadLine()) != null)
            collection.Add(input);

        Assert.AreEqual(6, collection.Count);
    }
}

注意:我更改了上面的一些语法,但没有在 Test 方法中编译。更重要的是第一个方法似乎返回一个空流(我的 reader.ReadLine() 总是读取一次)。不知道我做错了什么。谢谢。

【问题讨论】:

    标签: c# memorystream streamwriter


    【解决方案1】:

    您忘记刷新您的 StreamWriter 实例。

    public static Stream Foo()
    {
        var memStream = new MemoryStream();
        var streamWriter = new StreamWriter(memStream);
    
        for (int i = 0; i < 6; i++)
            streamWriter.WriteLine("TEST");
    
        streamWriter.Flush();                                   <-- need this
        memStream.Seek(0, SeekOrigin.Begin);
        return memStream;
    }
    

    还要注意StreamWriter 应该被处理掉,因为它实现了IDisposable,但这反过来又会产生另一个问题,它也会关闭底层的MemoryStream

    您确定要在此处返回MemoryStream 吗?

    我会把代码改成这样:

    public static byte[] Foo()
    {
        using (var memStream = new MemoryStream())
        using (var streamWriter = new StreamWriter(memStream))
        {
            for (int i = 0; i < 6; i++)
                streamWriter.WriteLine("TEST");
    
            streamWriter.Flush();
            return memStream.ToArray();
        }
    }
    
    [Test]
    public void TestStreamRowCount()
    {
        var bytes = Foo();
    
        using (var stream = new MemoryStream(bytes))
        using (var reader = new StreamReader(stream))
        {
            var collection = new List<string>();
            string input;
    
            while ((input = reader.ReadLine()) != null)
                collection.Add(input);
    
            Assert.AreEqual(6, collection.Count);
        }
    }
    

    【讨论】:

    • 我不同意将其转换为数组。 MemoryStream 可以充当普通的 ol Stream 并且大多数时候它的使用者并不关心它的实现。很多时候,您在测试时使用 MemoryStream,在生产期间使用文件流,例如
    • 出于我的目的,我确实想返回一个 Stream。出于同样的原因,马特上面提到了。刷新 StreamWriter 是我所缺少的。谢谢。
    • 我知道这是一篇古老的帖子。但它只是救了我。谢谢:)
    【解决方案2】:

    由于您没有使用“使用”或 streamWriter.Flush(),因此编写器没有提交对流的更改。结果 Stream itslef 还没有数据。一般来说,您希望使用使用来包装 Stream 和 StremaWriter 实例的操作。

    您还应该考虑返回 MemoryStream 的新实例:

    using(var memStream = new MemoryStream())
    {
       ....
       return new MemoryStream(memStream.ToArray(), false /*writable*/);
    }
    

    【讨论】:

    • 为什么要返回一个新的 MemoryStream 实例?这不是效率低下,而且是多余的吗?
    • 使其只读,停止使用为可写流分配的额外内存,以允许在创建流时“使用”正常的流代码模式。在这种特殊情况下,它不是很重要,但通常最好返回调用者可以以他们想要的任何方式使用的流,而不必担心下面的流是否会被关闭或更改。在这种特殊情况下,您可以通过使用 GetBuffer 而不是 ToArray(复制内部缓冲区)非常有效地创建新流。
    【解决方案3】:

    写完行后尝试刷新streamWriter。

    【讨论】:

    • 刷新流对我有帮助!只是一个旁注;我正在使用流编写器将 1348 个字节写入内存流。 1024 字节会写入(没有刷新),我花了很长时间才弄清楚,但最终刷新它移动了其他 324 字节。
    猜你喜欢
    • 1970-01-01
    • 2014-02-09
    • 1970-01-01
    • 2014-02-22
    • 2021-07-10
    • 2018-08-24
    • 1970-01-01
    • 2016-05-03
    • 1970-01-01
    相关资源
    最近更新 更多