使用从其他流创建的流时,如何使用语句作用域?



我遇到使用多个流通过http下载压缩文件的情况。为此,我需要使用多个流。即获取Web响应流,读入二进制读取器流,使用二进制写入器流写入内存流等。

由于这一切都有点复杂和令人讨厌,我已将所有内容拆分为小函数以使其读起来更好一些,但是我对从公共DownloadCsvReport函数调用的readStreamIntoMemoryStream函数有一些证明,请参见下文:

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;
        }
    }
}

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

这是 .NET Framework 中的一个设计缺陷,该缺陷已从 .NET 4.5 开始修复,您可以在其中使用BinaryWriterBinaryReader构造函数的重载,这些构造函数允许您在释放流后保持打开状态。

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;
}

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

问题是,BinaryWriterBinaryReader不是流。

它们作用于底层流,在您的情况下,底层流是memoryStream。所以,只要你关闭你的memoryStream和外responseStream,一切都很好。

编辑

事实上,看看他们的源代码:

protected virtual void Dispose(bool disposing)
{
    if (disposing)
        OutStream.Close();
}

如您所见,它所做的只是在底层流上调用Dispose。您当前的代码已经这样做了 - 因此无需处理编写器/读取器。这将是多余的。

相关内容

  • 没有找到相关文章

最新更新