Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/20.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何在C#中自动删除临时文件?_C#_.net_Temporary Files - Fatal编程技术网

如何在C#中自动删除临时文件?

如何在C#中自动删除临时文件?,c#,.net,temporary-files,C#,.net,Temporary Files,如果我的应用程序关闭或崩溃,有什么好方法可以确保删除临时文件?理想情况下,我希望获得一个临时文件,使用它,然后忘记它 现在,我保留了一个临时文件列表,并使用Application.ApplicationExit上触发的EventHandler删除它们 < >有更好的方法吗? < P>我不是主要的C程序员,但是C++中我会使用这个方法。有一些在线的,但大多数似乎使用终结器-这是不确定的 我认为有一些Windows SDK函数可以创建临时文件,但不知道它们是否会在程序终止时自动删除。有这个功能,但是

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

现在,我保留了一个临时文件列表,并使用Application.ApplicationExit上触发的EventHandler删除它们

< >有更好的方法吗?

< P>我不是主要的C程序员,但是C++中我会使用这个方法。有一些在线的,但大多数似乎使用终结器-这是不确定的

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


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

很高兴看到您愿意承担责任,但是如果文件不是很大(>50MB),您将与所有人(包括MS)一样将它们保留在临时目录中。磁盘空间丰富


如前所述,GetTempPath是一条路要走。空间不足的用户将能够运行磁盘清理,您的文件(以及其他所有人的文件)将被清理。

如果进程过早终止,则无法保证任何事情,但是,我使用“
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
被释放或垃圾回收时,该文件将被删除(如果可能)。很明显,您可以根据自己的喜好在某个地方的集合中使用它。您可以在关闭时传递
文件\u标志\u删除\u标志。这会告诉Windows在关闭所有句柄后删除该文件。另请参见:。

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

我将使用.NET
TempFileCollection
类,因为它是内置的,在.NET的旧版本中可用,并实现
IDisposable
接口,因此如果与
“using”
关键字一起使用,则会在使用后进行清理

下面是一个从嵌入式资源中提取文本的示例(通过项目属性页->资源选项卡添加,如下所述:,然后在嵌入式文件的属性设置中设置为
“EmbeddedResource”


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

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

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)) { }
            }
        }
    }
}
每次需要临时文件使用时:

var tempFile = TemporaryFiles.UseNew();
确保在应用程序关闭或崩溃后删除所有临时文件

TemporaryFiles.DeleteAllPreviouslyUsed();

在应用程序启动时。

如果要构建Windows窗体应用程序,可以使用以下代码:

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

析构函数通常用于按类释放句柄和资源。我想你可以用它来删除文件,但这应该由创建它们的应用程序代码来处理?据我所知,确定性意味着您不知道它将在何时运行,但通常您可以确定它将运行(当然,除非您拔下电源线)——或者我在这里错了吗?当进程异常退出时,我希望如何工作?OP特别询问“…或崩溃”。@MarkusSchaber:如果这是一个例外,RAII工作正常,如果你把电源线拉到电脑上,它不会有帮助。:)@csl:还有其他方法(如硬进程终止)阻止RAII工作。我个人认为临时文件就是临时文件,应该在不再需要时立即销毁。我讨厌我的磁盘被各种各样的垃圾弄得乱七八糟。没有人(包括微软)关心我电脑的状态,这真是可耻……同意。。无论出于何种原因,如果您无法清理所有文件,最好将它们放在临时目录中,而不要放在其他任何地方。人们不喜欢真相与理想不符的情况。问题是Windows无法知道何时删除临时文件,因此它必须将它们留在磁盘上,让程序员记住删除它们。如果他们真的记得那就好了!遗憾的是,更多的程序员不使用FileOptions deleteonclose。对于大多数应用程序来说,在突然断电的情况下,保留临时文件可能是“正常的”。当进程被终止时,它也可能被认为是正常的。如果应用程序既没有因断电(或类似情况)而停止运行,也没有因断电(或类似情况)而中断,那么保留临时文件当然不是件难事。遗憾的是.NET的文件类中没有类似Java的deleteOnExit()的东西。。。并不是说如果一个文件没有关闭,它就可以正常工作。你不经常看到一个合适的地方使用一个空的catch块。我可能会实现一个变体。这是一个简单易懂的代码。这个代码可以删除其他人使用的临时文件吗applications@KevinPanko因为我没有花时间考虑所有可能的继承场景,以确定它在子类化时是否会按照预期的方式运行。如果你想这样做,请随意,@PMBjornerud yes,在这种情况下;这里终结器的用途与
文件
对象无关。这与类的意图有关,即(参见问题)在完成时删除文件。即使有人未能正确地处理它,我们也希望这样做。我们甚至没有
文件
实例。如果需要多次打开该文件(例如,稍后或通过另一个进程),请小心使用此方法。例如,如果您希望打开、填充和关闭文件,它可能会立即消失,因此您无法使用刚刚创建的内容。您必须让原始句柄保持足够长的打开时间,以便打开第二个句柄,但如果没有使用适当的标志打开,则可能会导致共享冲突。在.NET4(可能更早)中
    private void Form1_FormClosing(object sender, FormClosingEventArgs e)
    {
        File.Delete("temp.data");
    }