C# MemoryStream在返回时禁用读取
在我的程序中,我基本上是读取一个文件,对其进行一些处理,然后将其作为内存流传递回主程序,由streamreader处理。这一切都将由我的主服务器旁边的一个类来处理 问题是,当我从另一个类中的方法返回内存流时,“canread”变量设置为false,从而导致streamreader初始化失败 下面是发生问题的一个示例(虽然在这里我正在写入另一个类中的memorystream,但当我将它传回时,它仍然会导致相同的错误) 在名为“Otherclass”的类中: 该函数在主程序中调用:C# MemoryStream在返回时禁用读取,c#,stream,memorystream,C#,Stream,Memorystream,在我的程序中,我基本上是读取一个文件,对其进行一些处理,然后将其作为内存流传递回主程序,由streamreader处理。这一切都将由我的主服务器旁边的一个类来处理 问题是,当我从另一个类中的方法返回内存流时,“canread”变量设置为false,从而导致streamreader初始化失败 下面是发生问题的一个示例(虽然在这里我正在写入另一个类中的memorystream,但当我将它传回时,它仍然会导致相同的错误) 在名为“Otherclass”的类中: 该函数在主程序中调用: MemorySt
MemoryStream MStream = Otherclass.ImportantStreamManipulator();
StreamReader reader = new StreamReader(MStream);
当我在“return MemStream”上设置断点时,“CanRead”属性仍然设置为true。一旦我执行步骤使其返回到我的主函数,并将返回的值写入MStream,“CanRead”属性设置为false。这会导致StreamReader中出现异常,表示无法读取MStream(如属性所示).数据应该在streams缓冲区中,但我就是拿不出来
我如何设置它以便“可以阅读”一旦返回到我的main,是否会报告true?或者我是否误解了MemoryStream的工作原理以及我将如何完成我想做的事情?StreamWriter拥有内存流的所有权,并且当
using
语句结束时,MemoryStream
也会关闭
请参阅。这就是问题所在:
using (writer)
{
//Code that writes stuff to the memorystream via streamwriter
return MemStream;
}
您正在关闭写入程序,这将关闭MemoryStream
。在这种情况下,您不想这样做…尽管您确实需要刷新写入程序,然后倒回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;
}
正如其他人所说,问题在于当StreamWriter关闭时,流是关闭的。一种可能的处理方法是返回字节数组而不是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());
}
}
另一种方法是在返回之前将流复制到另一个流。但是,这仍然存在一个问题,即随后使用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());
}
}
Jon,如果
writer
在使用stream
之前进行了GC,会发生什么情况?@KevinBrock:那么它只是垃圾收集,所有缓冲数据都会丢失。StreamWriter
没有终结器,AFAIK。确实如此。我认为返回它会在使用之前发送一个非封闭版本,然后再处理streamwriter。我想我在想,返回将返回MemoryStream的副本,而不是出于某种原因的引用。我还认为,通过返回保留ImportantStreamManipulator方法将自动处理streamwriter,因此我不确定这是否可行。streamwriter是否会在稍后的某个时间被处理他通过GC处理程序,还是只有在我处理MemoryStream或关闭程序后才会处理它?@xantam:你不需要处理StreamWriter
。它没有任何非托管资源。它在最终使用后的任何时候都会被垃圾收集,可能是在刷新调用.MemoryStrea之后m、 ToArray()甚至可以在基础流关闭时工作。您无法访问关闭的流,但数据仍然存在。
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());
}
}