How do I automatically delete tempfiles in c#?
有什么好的方法可以确保在我的应用程序关闭或崩溃时删除临时文件? 理想情况下,我想获取一个临时文件,使用它,然后再忽略它。
现在,我保留了一个临时文件列表,并使用在Application.ApplicationExit上触发的事件处理程序将其删除。
有没有更好的办法?
如果过早地终止了进程,则无法保证,但是,我使用"
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 | 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)); } } |
现在,当
考虑使用FileOptions.DeleteOnClose标志:
1 2 3 4 5 6 7 8 | 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 |
您可以P /调用
我将使用.NET
这是一个从嵌入式资源中提取文本的示例(通过项目属性页->资源选项卡添加,如下所述:如何将文本文件嵌入.NET程序集中?然后在嵌入式文件的属性设置中设置为
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | // 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."); } |
很高兴看到您要负责,但是如果文件不大(> 50MB),则将每个人(包括MS)保留在temp目录中将是符合您要求的。磁盘空间丰富。
正如csl所发布的,GetTempPath是必经之路。空间不足的用户将可以运行磁盘清理,并且您的文件(以及其他所有人的文件)也将被清理。
我主要不是C#程序员,但是在C ++中,我将为此使用RAII。有一些关于在C#在线中使用类似RAII的行为的提示,但大多数似乎都使用了不确定性的终结器。
我认为有一些Windows SDK函数可以创建临时文件,但是不知道它们是否在程序终止时自动删除。有GetTempPath函数,但是仅当您注销或重新启动IIRC时,那里的文件才被删除。
附言C#析构函数文档说您可以并且应该在那里释放资源,我觉得有些奇怪。如果是这样,您可以简单地删除析构函数中的临时文件,但是同样,这可能不是完全确定的。
我使用一个更可靠的解决方案:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 | using System.IO; using System.Reflection; namespace Konard.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)) { } } } } } |
每次需要临时文件时:
1 | var tempFile = TemporaryFiles.UseNew(); |
确保在应用程序关闭或崩溃后删除所有临时文件
1 | TemporaryFiles.DeleteAllPreviouslyUsed(); |
在应用程序启动时。
您可以在启动时启动一个线程,该线程将删除"不应该"从崩溃中恢复时存在的文件。
如果要构建Windows窗体应用程序,则可以使用以下代码:
1 2 3 4 | private void Form1_FormClosing(object sender, FormClosingEventArgs e) { File.Delete("temp.data"); } |