9

在我的程序中,我基本上是在读取一个文件,对其进行一些处理,然后将其作为内存流传递回主程序,这将由流读取器处理。这一切都将由我的主要课程旁边的一个班级处理。

问题是,当我从另一个类中的方法返回内存流时,“canread”变量设置为 false,从而导致流读取器初始化失败。

下面是发生问题的示例(尽管在这里我正在写入另一个类中的内存流,但是当我将其传回时它仍然会导致相同的错误。

在名为“Otherclass”的类中:

public static MemoryStream ImportantStreamManipulator()
{
   MemoryStream MemStream = new MemoryStream();

   StreamWriter writer = new StreamWriter(MemStream);
   using (writer)
   {
       //Code that writes stuff to the memorystream via streamwriter

       return MemStream;
   }
}

主程序中的函数调用:

MemoryStream MStream = Otherclass.ImportantStreamManipulator();
StreamReader reader = new StreamReader(MStream);

当我在“return MemStream”上放置断点时,“CanRead”属性仍然设置为 true。一旦我执行到返回主函数并将返回值写入 MStream 的步骤,“CanRead”属性将设置为 false。然后这会导致 StreamReader 中出现异常,指出无法读取 MStream(如属性所示)。数据应该在流缓冲区中,但我就是无法将其取出。

如何设置它以便“CanRead”在返回到我的主目录后报告为真?还是我误解了 MemoryStream 的工作原理以及我将如何完成我想做的事情?

4

3 回答 3

29

这就是问题:

using (writer)
{
    //Code that writes stuff to the memorystream via streamwriter

    return MemStream;
}

您正在关闭作者,这将关闭MemoryStream. 在这种情况下,您不想这样做……尽管您确实需要刷新writer,然后倒带MemoryStream. 只需将您的代码更改为:

public static MemoryStream ImportantStreamManipulator()
{
   // Probably add a comment here stating that the lack of using statements
   // is deliberate.
   MemoryStream stream = new MemoryStream();

   StreamWriter writer = new StreamWriter(stream);
   // Code that writes stuff to the memorystream via streamwriter

   writer.Flush();
   stream.Position = 0;
   return stream;
}
于 2012-07-17T18:38:41.027 回答
2

获得内存流的StreamWriter所有权,当using语句结束时,MemoryStream也关闭。

请参阅是否有任何方法可以在不关闭其 BaseStream 的情况下关闭 StreamWriter?.

于 2012-07-17T18:38:38.163 回答
0

正如其他人所说,问题在于 StreamWriter 关闭时 Stream 关​​闭。处理此问题的一种可能方法是返回字节数组而不是 MemoryStream。这避免了垃圾收集器必须处理的可能长时间运行的对象。

public static void Main()
{
    OutputData(GetData());
}

public static byte[] GetData()
{
    byte[] binaryData = null;

    using (MemoryStream ms = new MemoryStream())
    using (StreamWriter sw = new StreamWriter(ms))
    {
        string data = "My test data is really great!";

        sw.Write(data);
        sw.Flush();

        binaryData = ms.ToArray();
    }

    return binaryData;
}

public static void OutputData(byte[] binaryData)
{
    using (MemoryStream ms = new MemoryStream(binaryData))
    using (StreamReader sr = new StreamReader(ms))
    {
        Console.WriteLine(sr.ReadToEnd());
    }
}

另一种方法是在返回之前将 Stream 复制到另一个流。但是,这仍然存在后续使用 StreamReader 访问它会关闭该流的问题。

public static void RunSnippet()
{
    OutputData(GetData());
}

public static MemoryStream GetData()
{
    MemoryStream outputStream = new MemoryStream();

    using (MemoryStream ms = new MemoryStream())
    using (StreamWriter sw = new StreamWriter(ms))
    {
        string data = "My test data is really great!";

        sw.Write(data);
        sw.Flush();

        ms.WriteTo(outputStream);
        outputStream.Seek(0, SeekOrigin.Begin);
    }

    return outputStream;
}

public static void OutputData(MemoryStream inputStream)
{
    using (StreamReader sr = new StreamReader(inputStream))
    {
        Console.WriteLine(sr.ReadToEnd());
    }
}   
于 2012-07-17T19:12:16.503 回答