2014-02-24 23 views
1

我有一种情况,我正在使用多个流通过http下载压缩文件。为此,我需要使用多个流。即获取Web响应流,读入二进制读取器流,使用二进制写入器流写入内存流等。使用声明范围如何在使用从其他Stream创建的Stream时工作?

因为它有点复杂和讨厌,我已经把所有东西都分成了小函数,使它读取了一点更好,但我有一点与readStreamIntoMemoryStream功能,我从公众DownloadCsvReport函数调用provlem的,见下图:

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

我不确定是事情无论从私人的BinaryWriterBinaryReader流函数将在MemoryStream是公共方法失去范围时处理掉?如果不是,我用私有方法将这些流封装在使用语句中,当我尝试访问公共方法中的MemoryStream时它是否会抛出异常?

回答

1

我不确定的事情关于当公共方法丢失范围时,MemoryStream是否会抛弃来自私有函数的BinaryWriter和BinaryReader流?

的事情是,BinaryWriterBinaryReader流。

它们会对底层流进行操作,在您的情况下,它是memoryStream。 所以,只要你关闭你的memoryStream和外部responseStream,一切都很好。

编辑

其实,看看他们的source code

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

正如你所看到的,它是所有底层的流上调用Dispose。你现在的代码已经做到了 - 所以不需要处理作者/读者。这将是多余的。

+0

很酷的东西,应该考虑检查一下自己。干杯。 – jcvandan

2

这是.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.0(或更早),您可以使用从乔恩斯基特的MiscUtilNonClosingStreamWrapper类:

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

但是这肯定会否定这个观点?我希望它们被关闭,就在我关闭调用方法中的'MemoryStream'时!这是不是跟没有配置一样? – jcvandan

+0

@dormisher:如果您不在'readStreamIntoMemoryStream'方法中处理'BinaryWriter'和'BinaryReader',那么它们将保持打开状态,直到被垃圾收集器处理。通过使用“IDisposable”模式,您可以确保在不再需要它们时立即处理它们。 – Douglas

+0

好吧,感谢您的帮助。我使用.NET 4,所以不幸的是我不能使用这些重载,所以我不得不重构我的方法,所以我创建了所有我的流在公共方法。 – jcvandan

相关问题