如何确保应用程序关闭或崩溃时删除临时文件? 最理想的情况是,我希望获取一个临时文件,使用它,然后忘记它。
目前,我会保留我的临时文件列表,并使用在Application.ApplicationExit上触发的EventHandler来删除它们。
是否有更好的方法?
如何确保应用程序关闭或崩溃时删除临时文件? 最理想的情况是,我希望获取一个临时文件,使用它,然后忘记它。
目前,我会保留我的临时文件列表,并使用在Application.ApplicationExit上触发的EventHandler来删除它们。
是否有更好的方法?
如果进程被提前杀死,那就没有什么是可以保证的,但是我使用"using
"来做这件事..
using System;
using System.IO;
sealed class TempFile : IDisposable
{
string path;
public TempFile() : this(System.IO.Path.GetTempFileName()) { }
public TempFile(string path)
{
if (string.IsNullOrEmpty(path)) throw new ArgumentNullException("path");
this.path = path;
}
public string Path
{
get
{
if (path == null) throw new ObjectDisposedException(GetType().Name);
return path;
}
}
~TempFile() { Dispose(false); }
public void Dispose() { Dispose(true); }
private void Dispose(bool disposing)
{
if (disposing)
{
GC.SuppressFinalize(this);
}
if (path != null)
{
try { File.Delete(path); }
catch { } // best effort
path = null;
}
}
}
static class Program
{
static void Main()
{
string path;
using (var tmp = new TempFile())
{
path = tmp.Path;
Console.WriteLine(File.Exists(path));
}
Console.WriteLine(File.Exists(path));
}
}
现在,当TempFile
被处理或垃圾回收时,该文件将被删除(如果可能)。你可以根据需要将其作为紧密范围的使用,或者收集到某个地方使用。
File
对象无关。它与类的意图有关,即(参见问题)在完成时删除文件。我们想要这样做,即使有人未能正确地使用 Dispose()
。我们甚至没有一个 File
实例。 - Marc Gravell考虑使用FileOptions.DeleteOnClose标志:
using (FileStream fs = new FileStream(Path.GetTempFileName(),
FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.None,
4096, FileOptions.RandomAccess | FileOptions.DeleteOnClose))
{
// temp file exists
}
// temp file is gone
FileOptions.CreateNew
,但我保留了FileMode.OpenOrCreate
,因为你有意选择了它。 - piedarPath.GetTempFileName()
已经创建了文件,因此 FileOptions.CreateNew
不起作用并会抛出一个 IOException: The file ... already exists
。 - Bouke您可以使用P/Invoke CreateFile
并传递FILE_FLAG_DELETE_ON_CLOSE
标志。这告诉Windows在所有句柄关闭后删除文件。另请参见:Win32 CreateFile
文档。
DeleteOnClose
来实现这一点。 - Paul Groke // Extracts the contents of the embedded file, writes them to a temp file, executes it, and cleans up automatically on exit.
private void ExtractAndRunMyScript()
{
string vbsFilePath;
// By default, TempFileCollection cleans up after itself.
using (var tempFiles = new System.CodeDom.Compiler.TempFileCollection())
{
vbsFilePath= tempFiles.AddExtension("vbs");
// Using IntelliSense will display the name, but it's the file name
// minus its extension.
System.IO.File.WriteAllText(vbsFilePath, global::Instrumentation.Properties.Resources.MyEmbeddedFileNameWithoutExtension);
RunMyScript(vbsFilePath);
}
System.Diagnostics.Debug.Assert(!File.Exists(vbsFilePath), @"Temp file """ + vbsFilePath+ @""" has not been deleted.");
}
我使用了更可靠的解决方案:
using System.IO;
using System.Reflection;
namespace Helpers
{
public static partial class TemporaryFiles
{
private const string UserFilesListFilenamePrefix = ".used-temporary-files.txt";
static private readonly object UsedFilesListLock = new object();
private static string GetUsedFilesListFilename()
{
return Assembly.GetEntryAssembly().Location + UserFilesListFilenamePrefix;
}
private static void AddToUsedFilesList(string filename)
{
lock (UsedFilesListLock)
{
using (var writer = File.AppendText(GetUsedFilesListFilename()))
writer.WriteLine(filename);
}
}
public static string UseNew()
{
var filename = Path.GetTempFileName();
AddToUsedFilesList(filename);
return filename;
}
public static void DeleteAllPreviouslyUsed()
{
lock (UsedFilesListLock)
{
var usedFilesListFilename = GetUsedFilesListFilename();
if (!File.Exists(usedFilesListFilename))
return;
using (var listFile = File.Open(usedFilesListFilename, FileMode.Open))
{
using (var reader = new StreamReader(listFile))
{
string tempFileToDelete;
while ((tempFileToDelete = reader.ReadLine()) != null)
{
if (File.Exists(tempFileToDelete))
File.Delete(tempFileToDelete);
}
}
}
// Clean up
using (File.Open(usedFilesListFilename, FileMode.Truncate)) { }
}
}
}
}
每次需要临时文件时,请使用以下方法:
var tempFile = TemporaryFiles.UseNew();
TemporaryFiles.DeleteAllPreviouslyUsed();
我不是主要的C#程序员,但在C++中,我会使用RAII。有一些关于在C#中使用类似RAII行为的提示在线上,但大多数似乎使用终结器-这是不确定的。
我认为有一些Windows SDK函数可以创建临时文件,但不知道它们是否在程序终止时自动删除。有GetTempPath函数,但其中的文件仅在注销或重新启动时才会被删除,如果我没记错的话。
附注:C# 析构函数文档 表示您可以并且应该在其中释放资源,我觉得有点奇怪。 如果是这样,您可以在析构函数中简单地删除临时文件,但这可能不完全确定。
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
File.Delete("temp.data");
}