如何自动删除 c# 中的临时文件?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/400140/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-04 01:59:55  来源:igfitidea点击:

How do I automatically delete tempfiles in c#?

c#.nettemporary-files

提问by Nifle

What are a good way to ensure that a tempfile is deleted if my application closes or crashes? Ideally I would like to obtain a tempfile, use it and then forget about it.

如果我的应用程序关闭或崩溃,确保删除临时文件的好方法是什么?理想情况下,我想获得一个临时文件,使用它然后忘记它。

Right now I keep a list of my tempfiles and delete them with an eventhandler that triggers on Application.ApplicationExit.

现在,我保留了我的临时文件列表,并使用在 Application.ApplicationExit 上触发的事件处理程序删除它们。

Is there a better way?

有没有更好的办法?

采纳答案by Marc Gravell

Nothing is guaranteed if the process is killed prematurely, however, I use "using" to do this..

如果进程过早终止,则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));
    }
}

Now when the TempFileis disposed or garbage-collected the file is deleted (if possible). You could obviously use this as tightly-scoped as you like, or in a collection somewhere.

现在,当TempFile处理或垃圾收集时,文件将被删除(如果可能)。显然,您可以根据自己的喜好在严格范围内使用它,或者在某个集合中使用它。

回答by csl

I'm not primarily a C# programmer, but in C++ I'd use RAIIfor this. There are some hints on using RAII-like behaviour in C#online, but most seem to use the finalizer — which is not deterministic.

我主要不是 C# 程序员,但在 C++ 中,我会为此使用RAII。有一些关于在 C# 中使用类似 RAII 的行为的在线提示,但大多数似乎使用终结器——这不是确定性的。

I think there are some Windows SDK functions to create temporary files, but don't know if they are automatically deleted on program termination. There is the GetTempPathfunction, but files there are only deleted when you log out or restart, IIRC.

我认为有一些Windows SDK功能可以创建临时文件,但不知道它们是否会在程序终止时自动删除。有GetTempPath功能,但只有在您注销或重新启动时才会删除那里的文件,IIRC。

P.S. The C# destructor documentationsays you can and should release resources there, which I find a bit odd. If so, you could simply delete the tempfile in the destructor, but again, this might not be completely deterministic.

PS C# 析构函数文档说你可以而且应该在那里释放资源,我觉得这有点奇怪。如果是这样,您可以简单地删除析构函数中的临时文件,但同样,这可能不是完全确定的。

回答by StingyHyman

Its nice to see that you want to be responsible, but if the files aren't huge (>50MB) you would be in line with everyone (MS included) in leaving them in the temp directory. Disk space is abundant.

很高兴看到您想要负责,但如果文件不是很大(> 50MB),您将与每个人(包括 MS)保持一致,将它们留在临时目录中。磁盘空间充足。

As csl posted, the GetTempPath is the way to go. Users who are short on space will be able to run disk cleanup and your files (along with everyone else's) will be cleaned up.

正如 csl 发布的那样, GetTempPath 是要走的路。空间不足的用户将能够运行磁盘清理,您的文件(以及其他人的)将被清理。

回答by David Grant

You could P/Invoke CreateFileand pass the FILE_FLAG_DELETE_ON_CLOSEflag. This tells Windows to delete the file once all handles are closed. See also: Win32 CreateFiledocs.

您可以P/InvokeCreateFile并传递FILE_FLAG_DELETE_ON_CLOSE标志。这告诉 Windows 在关闭所有句柄后删除文件。另请参阅:Win32CreateFile文档

回答by Austin Salonen

You could launch a thread on startup that will delete files that exist when they "shouldn't" to recover from your crash.

您可以在启动时启动一个线程,该线程将删除“不应该”存在的文件以从崩溃中恢复。

回答by user3454591

I would use the .NET TempFileCollectionclass, as it's built-in, available in old versions of .NET, and implements the IDisposableinterface and thus cleans up after itself if used e.g. in conjunction with the "using"keyword.

我会使用 .NETTempFileCollection类,因为它是内置的,可在旧版本的 .NET 中使用,并实现IDisposable接口,因此如果与"using"关键字结合使用,则在其自身之后进行清理。

Here's an example that extracts text from an embedded resource (added via the projects property pages -> Resources tab as described here: How to embed a text file in a .NET assembly?, then set to "EmbeddedResource"in the embedded file's property settings).

这是从嵌入资源中提取文本的示例(通过项目属性页添加 -> 资源选项卡,如下所述:How to embed a text file in a .NET assembly?,然后"EmbeddedResource"在嵌入文件的属性设置中设置为 )。

    // 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.");
    }

回答by DanW

Consider using the FileOptions.DeleteOnClose flag:

考虑使用 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

回答by Konard

I use a more reliable solution:

我使用更可靠的解决方案:

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)) { }
            }
        }
    }
}

Every time you need temporary file use:

每次需要临时文件时使用:

var tempFile = TemporaryFiles.UseNew();

To be sure all temporary files are deleted after application closes or crashes put

确保在应用程序关闭或崩溃后删除所有临时文件

TemporaryFiles.DeleteAllPreviouslyUsed();

at start of the application.

在应用程序开始时。

回答by Zach

If you're building a Windows Forms Application, you can use this code:

如果您正在构建 Windows 窗体应用程序,则可以使用以下代码:

    private void Form1_FormClosing(object sender, FormClosingEventArgs e)
    {
        File.Delete("temp.data");
    }