我有一个应用程序,它根据字符串列表处理文件流,字符串可以是磁盘上的文件,也可以是Zip文件中的文件。要清理代码,我想重构打开文件的过程。
我已经创建了一个返回文件内容Stream的方法,但是因为流依赖于ZipFile IDisposable,所以当我读取流时,ZipFile会被抛出异常。
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子句,但我怀疑它们是否会被处理掉。当它取决于其他一次性用品时,是否有合适的模式来退回一次性用品?
答案 0 :(得分:2)
不要直接返回流,而是返回一个一次性对象,该对象可以提供您想要处理的流,但是当它被处置时清除该流和其他相关资源的:
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();
}
}
然后返回那个,而不是流本身。如果值得花时间,你可以将该包装器转换为Stream
本身,只将所有Stream
方法转发到合成流中,但这样做会在处理时完成额外的工作。是否值得花时间创建更具参与性的包装而不是让调用者访问Stream
属性取决于您。
答案 1 :(得分:1)
您可能应该将文件从ZipEntry
复制到MemoryStream
,以便您可以使用副本。
//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;
}