使用临时文件流进行处理

sh0*_*ged 6 c# dispose stream filestream

假设我想定义一个使用Path.GetTempFileName()方法创建临时文件的TempFileStream类.当不再需要TempFileStream的对象时,必须删除临时文件,例如关闭或处置:

class TempFileStream: FileStream
{
  string m_TempFileName = Path.GetTempFileName();
  public TempFileStream(FileMode fileMode): base(m_TempFileName,fileMode) {}

  /// ...

 public ovverride Dispose(bool disposing)
 {
   /// ???
 }

}   
Run Code Online (Sandbox Code Playgroud)

我该如何简单安全地实现这一目标?

Ext*_*ank 26

试试这个:

public class TempFileStream : FileStream
{
    public TempFileStream()
        : base(Path.GetTempFileName(), FileMode.Create, FileAccess.ReadWrite, FileShare.Read, 4096, FileOptions.DeleteOnClose) { }
    public TempFileStream(FileAccess access)
        : base(Path.GetTempFileName(), FileMode.Create, access, FileShare.Read, 4096, FileOptions.DeleteOnClose) { }
    public TempFileStream(FileAccess access, FileShare share)
        : base(Path.GetTempFileName(), FileMode.Create, access, share, 4096, FileOptions.DeleteOnClose) { }
    public TempFileStream(FileAccess access, FileShare share, int bufferSize)
        : base(Path.GetTempFileName(), FileMode.Create, access, share, bufferSize, FileOptions.DeleteOnClose) { }
}
Run Code Online (Sandbox Code Playgroud)

FileOptions.DeleteOnClose选项将确保操作系统在关闭文件时自动删除临时文件.不需要特殊的Dispose方法,因为它全部都为您服务.

  • 为DeleteOnClose +1,不知道那一个,方便! (2认同)
  • +1,我喜欢在这个网站上阅读其他人的答案我学到了多少. (2认同)

Rob*_*ney 5

这是一个有趣的想法,但是这个设计让我感到困扰.如果您已经在设计中解决了这个问题,请原谅我.但是如果你的设计只是一个简单的包装FileStream,那么我认为这是一个微妙的问题.

如果您在流关闭时删除文件,这意味着实际使用文件中数据的唯一方法FileAccessReadWrite.正确?换句话说,您将使用包含如下代码的文件:

using (TempFileStream t as new TempFileStream())
{
   WriteDataToTempFile(t);
   t.Seek(0, SeekOrigin.Begin);
   ReadDataFromTempFile(t);
}
Run Code Online (Sandbox Code Playgroud)

我看到的问题ReadDataFromTempFile是期望文件被打开以进行读访问,而不是读/写访问.这为我认为很难找到的一些错误打开了大门.考虑这样的代码:

using (TempFileStream t as new TempFileStream())
{
   MyClass o = new MyClass(o);
   o.TempStream = t;
   o.ProduceOutput();
   t.Seek(0, SeekOrigin.Begin);
   o.ProcessOutput();
}
Run Code Online (Sandbox Code Playgroud)

......与此相比:

MyClass o = new MyClass();
string n = Path.GetTempFileName();
using (FileStream s = new FileStream(n, FileMode.Create, FileAccess.Write))
{
   o.TempStream = t;
   o.ProduceOutput();
}
using (FileStream s = new FileStream(n, FileMode.Open, FileAccess.Read))
{
   o.TempStream = t;
   o.ProcessOutput();
}
File.Delete(n);
Run Code Online (Sandbox Code Playgroud)

当然,第一种方法比第二种方法短.但是如果ProcessOutput调用写入的方法,第二种方法将抛出异常TempStream.(或者设置一个属性,其set访问器引发一个事件,其事件处理程序调度对写入的方法的调用TempStream,该问题可能最终会发生.)第一个只会产生意外的结果,没有明显的原因.

我认为,你可以通过让你的TempFileStream班级打开基础FileStream使用来解决这个问题FileAccess.Write.然后实现一个Rewind关闭它的方法FileStream并创建一个使用的新方法FileAccess.Read.如果你这样做,任何试图在文件打开以进行读访问时写入的方法(反之亦然)将至少抛出异常.


Jul*_*ain 2

base.Dispose(disposing); // disposes the base stream so the file is no longer used
if (disposing)
    File.Delete(m_TempFileName); // deletes the file
Run Code Online (Sandbox Code Playgroud)

如果需要,您应该为 File.Delete 添加适当的异常处理。