C# 在使用Stream';从其他流创建的';s

C# 在使用Stream';从其他流创建的';s,c#,.net,stream,using,C#,.net,Stream,Using,我有一种情况,我使用多个流通过http下载压缩文件。为此,我需要使用多个流。例如,获取web响应流,读入二进制读取器流,使用二进制写入器流写入内存流等 由于这一切都有点复杂和令人讨厌,我已经将所有内容拆分为一些小函数,以使其可读性更好,但我对从公共下载csvreport函数调用的readstreamintomorystream函数有点疑问,请参见下文: public IEnumerable<string> DownloadCsvReport(string reportDownload

我有一种情况,我使用多个流通过http下载压缩文件。为此,我需要使用多个流。例如,获取web响应流,读入二进制读取器流,使用二进制写入器流写入内存流等

由于这一切都有点复杂和令人讨厌,我已经将所有内容拆分为一些小函数,以使其可读性更好,但我对从公共
下载csvreport
函数调用的
readstreamintomorystream
函数有点疑问,请参见下文:

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;
        }
    }
}
public IEnumerable DownloadCsvReport(字符串报告downloadURL)
{
使用(Stream responseStream=creatDownloadWebRequest(reportDownloadUrl))
使用(MemoryStream MemoryStream=ReadStreamInMemoryStream(responseStream))
{
将memoryStream设置为开始(memoryStream);
ZipEntry ZipEntry=从memoryStream(memoryStream)获取压缩文件;
返回convertedzippedfiletocsvrows(zipEntry);
}
}
私有MemoryStream ReadStreamInMemoryStream(Stream webResponseStream)
{
var memoryStream=新的memoryStream();
var binaryWriter=新的binaryWriter(memoryStream);
var binaryReader=新的binaryReader(webResponseStream);
while(true)
{
byte[]buffer=binaryReader.ReadBytes(BufferSize);
写入(缓冲区);
if(buffer.Length!=BufferSize)
{
返回内存流;
}
}
}

我不确定的是,当
MemoryStream
是公共方法失去作用域时,来自私有函数的
BinaryWriter
BinaryReader
流是否会被处理掉?如果不是,并且我在私有方法中使用语句包装了这些流,那么当我尝试访问公共方法中的
MemoryStream
时,它不会引发异常吗?

这是.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库中的
NonClosingStreamWrapper
类:

我不确定的是,当公共方法失去作用域时,MemoryStream是否会处理来自私有函数的BinaryWriter和BinaryReader流

事情是这样的,而且不是这样的

它们作用于底层流,在您的例子中,底层流是
memoryStream
。 因此,只要您关闭
内存流
和外部
响应流
,一切都很好

编辑

事实上,看看他们的:


如您所见,它所做的只是调用底层流上的
Dispose
。您当前的代码已经做到了这一点,因此不需要处理writer/reader。这是多余的。

但这肯定违背了重点吗?我希望在我从调用方法关闭
MemoryStream
时关闭它们!这样做是否与根本不处理相同?@dormisher:如果不在
ReadStreamInMemoryStream
方法中处理
BinaryWriter
BinaryReader
,那么它们将保持打开状态,直到垃圾收集器处理。通过使用
IDisposable
模式,您可以确保它们在不再需要时立即被处理。好的,很酷,谢谢您的帮助。我使用的是.NET4,所以很遗憾我不能使用这些重载,所以我被迫重构我的方法,以便在公共方法中创建所有流。很酷的东西,我应该自己考虑检查一下。干杯
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;
}
protected virtual void Dispose(bool disposing)
{
    if (disposing)
        OutStream.Close();
}