我遇到的情况是我使用多个流来通过http下载压缩文件。为此,我需要使用多个流。即获取Web响应流,读入二进制读取器流,使用二进制写入器流写入内存流等等。
因为它有点复杂和令人讨厌我已经将所有内容分成小函数以使它读得更好,但我对readStreamIntoMemoryStream
函数有一点问题我是从公共DownloadCsvReport
函数调用,请参见下文:
public IEnumerable<string> DownloadCsvReport(string reportDownloadUrl)
{
using (Stream responseStream = creatDownloadWebRequest(reportDownloadUrl))
using (MemoryStream memoryStream = readStreamIntoMemoryStream(responseStream))
{
setMemoryStreamToBegining(memoryStream);
ZipEntry zipEntry = getZippedFileFromMemoryStream(memoryStream);
return convertZippedFileToCsvRows(zipEntry);
}
}
private MemoryStream readStreamIntoMemoryStream(Stream webResponseStream)
{
var memoryStream = new MemoryStream();
var binaryWriter = new BinaryWriter(memoryStream);
var binaryReader = new BinaryReader(webResponseStream);
while (true)
{
byte[] buffer = binaryReader.ReadBytes(BufferSize);
binaryWriter.Write(buffer);
if (buffer.Length != BufferSize)
{
return memoryStream;
}
}
}
我不确定的是,当BinaryWriter
是公共方法失去范围时,来自私有函数的BinaryReader
和MemoryStream
流是否会被处理掉?如果没有,我将这些流包装在私有方法中的using语句中,当我尝试访问公共方法中的MemoryStream
时,是否会抛出异常?
答案 0 :(得分:2)
这是.NET Framework中的一个设计缺陷,自.NET 4.5开始修复,您可以使用BinaryWriter
和BinaryReader
构造函数的重载,让您打开流处理完毕后。
var memoryStream = new MemoryStream();
var encoding = new UTF8Encoding(false, true);
using (var binaryWriter = new BinaryWriter(memoryStream, encoding, true))
using (var binaryReader = new BinaryReader(webResponseStream, encoding, true))
{
// ...
return memoryStream;
}
编辑:如果您使用的是.NET 4(或更早版本),则可以使用Jon Skeet的MiscUtil库中的NonClosingStreamWrapper
类:
var memoryStream = new MemoryStream();
using (var memoryStreamWrapper = new NonClosingStreamWrapper(memoryStream))
using (var webResponseStreamWrapper = new NonClosingStreamWrapper(webResponseStream))
using (var binaryWriter = new BinaryWriter(memoryStreamWrapper))
using (var binaryReader = new BinaryReader(webResponseStreamWrapper))
{
// ...
return memoryStream;
}
答案 1 :(得分:1)
我不确定的是,当MemoryStream是公共方法失去范围时,来自私有函数的BinaryWriter和BinaryReader流是否会被处理掉?
问题是,BinaryWriter
和BinaryReader
不是流。
它们对基础流起作用,在您的情况下,它是memoryStream
。
因此,只要您关闭memoryStream
和外responseStream
,一切都会好的。
修改强>:
事实上,看看他们的source code:
protected virtual void Dispose(bool disposing)
{
if (disposing)
OutStream.Close();
}
如您所见,它只是在底层流上调用Dispose
。您当前的代码已经这样做了 - 所以不需要处理编写器/阅读器。这将是多余的。