C# 依赖于其他一次性物品的一次性物品
我有一个基于字符串列表处理文件流的应用程序,字符串可以是磁盘上的文件,也可以是Zip文件中的文件。为了清理代码,我想重构打开文件的过程 我创建了一个返回文件内容流的方法,但由于该流依赖于ZipFile IDisposable,所以在我读取该流时,ZipFile已被释放,并引发异常C# 依赖于其他一次性物品的一次性物品,c#,.net,C#,.net,我有一个基于字符串列表处理文件流的应用程序,字符串可以是磁盘上的文件,也可以是Zip文件中的文件。为了清理代码,我想重构打开文件的过程 我创建了一个返回文件内容流的方法,但由于该流依赖于ZipFile IDisposable,所以在我读取该流时,ZipFile已被释放,并引发异常 void Main() { using (var stream = OpenFileForImport("zipfile.zip;insidefile.txt")) new StreamRead
void Main()
{
using (var stream = OpenFileForImport("zipfile.zip;insidefile.txt"))
new StreamReader(stream).ReadToEnd(); // Exception
using (var stream = OpenFileForImport("outside.txt"))
new StreamReader(stream).ReadToEnd(); // Works
}
public static Stream OpenFileForImport(string filePath)
{
var path = Path.Combine(basefolder, filePath);
if (path.Contains(";"))
{
var parts = path.Split(';');
var zipPath = parts[0];
//Error checking logic to ensure zip file exists and is valid...
using (var zip = ZipFile.OpenRead(zipPath))
using (var entry = zip.GetEntry(parts[1]))
{
//Error checking logic to ensure inside file exists within zip file.
return entry.Open();
}
}
var file = new FileInfo(path);
if (file != null)
return file.OpenRead();
return null;
}
我可以从
zip
和entry
声明中删除using子句,但我怀疑它们是否会被处理掉。当一次性文件依赖于其他一次性文件时,是否有适当的模式返回该文件?您可能应该将文件从ZipEntry
复制到内存流中,以便有一个副本可供使用
//Error checking logic to ensure zip file exists and is valid...
using (var zip = ZipFile.OpenRead(zipPath))
using (var entry = zip.GetEntry(parts[1]))
{
//Error checking logic to ensure inside file exists within zip file.
MemoryStream stream = new MemoryStream();
entry.Open().CopyTo(stream);
stream.Seek(0, SeekOrigin.Begin);
return stream;
}
不要直接返回流,而是返回一个一次性对象,该对象可以提供要处理的流,但在处理该流时会清理该流和其他从属资源:
public class NameToBeDetermined : IDisposable
{
private ZipFile zip;
public Stream Stream { get; }
public NameToBeDetermined(ZipFile zip, Stream stream)
{
this.zip = zip;
Stream = stream;
}
public void Dispose()
{
zip.Dispose();
Stream.Dispose();
}
}
然后返回它,而不是流本身。如果值得花时间的话,您可以将该包装器转换为流
本身,它只是将所有流
方法转发到组合流中,但这会在处理时做额外的工作。是否值得花时间创建更复杂的包装,而不是让调用者访问流
属性,这取决于您。假设文件甚至可以放入内存。在任意zip中访问任意文件的方法几乎肯定不能做出这样的假设。@Servy这是真的,但我猜测对ReadToEnd
的调用应该是这样的。这只是一个示例调用,不一定代表每个调用(否则,该方法本身将读取整个内容并返回该内容,而不是流,如果您确实希望它将整个文件拉入内存,则应该这样做)。作为一般规则,如果返回流,我将在位置0处返回它。您可以返回一个自定义的流
实现,该实现拥有可处置项,并在其自己的Dispose
方法中处置它们。您需要使用封装并实现自己的类,该类使用Dispose接口。这就是我最终采用的解决方案你所说的“处理时做额外的工作”是什么意思?如果我处理所有包含的对象,包装器就位是否会带来任何风险?@MattMurrell“处理时做额外的工作”正在处理其他依赖对象。使用包装器您担心什么,您认为它会导致什么问题?