我需要在Windows Forms .NET 3.5应用程序中使用一些临时文件。这些文件在外部应用程序中打开,当然可以比我自己的程序运行更长的时间。
是否有任何最佳做法可以确保随时清理这些临时文件,以避免用不再需要的“垃圾”文件填充用户的硬盘?或者甚至是Windows自动处理这个?
一个很好的例子是任何邮件客户端:当你在任何应用程序中打开附件时,它通常被写入一个打开的临时文件。有没有办法弄清楚这些文件如何管理清理?
使用Google向我展示了许多清理和调整工具来手动清理临时目录,但我不想强迫用户这样做。 : - )
感谢任何帮助。
的Matthias
答案 0 :(得分:27)
在.NET中,您可以使用TempFileCollection
类来管理应用程序要清理的一组临时文件(请注意,它隐藏在CodeDom命名空间中)。显然你不能删除任何不属于你自己的文件,因为这些文件可能仍然被另一个应用程序打开(删除它们可能会导致严重的问题)。
答案 1 :(得分:6)
清理临时文件的责任应该在创建它们的应用程序上。这很容易。我使用的类看起来像这样:
public class TempFile : IDisposable
{
public TempFile()
{ this.path = System.IO.Path.GetTempFileName(); }
public void Dispose()
{ File.Delete(path); }
private string path;
public string Path { get { return path; } }
}
如果您需要清理其他应用程序的临时文件,则需要一些与您通信的方式。它至少应该能够提供信号量。然而,这样做的复杂性要大于让原始应用程序处理自己的文件的复杂性。
答案 2 :(得分:5)
如果您尝试确定性地清除Temporary Files类型文件夹的内容,则可能会删除其他进程正在使用的文件。 Windows操作系统提供的工具允许用户在卷的可用磁盘空间达到特定阈值时删除这些文件。
现在,如果您在使用特定临时文件后可以确定不再需要它,那么删除该特定文件没有任何缺陷。
答案 3 :(得分:2)
我们有类似的文件生命周期问题 - (winforms)应用程序可以从中央存储库中获取文档供用户查看,但用户应该能够关闭我们的应用程序,而不会影响他们正在查看的文件。出于安全考虑,需要清理文档文件,以免它们长时间存在。
我们使用的解决方案是在用户的隔离存储区域中创建一个带有日期派生名称的文件夹,并将其用作今天的缓存。在应用程序关闭和启动时,我们检查以前过时的缓存文件夹并删除它们(和内容)。
答案 4 :(得分:1)
我相信当用户退出时会删除它们。
回到人们每天关掉电脑的日子里,这可能是一个完美的解决方案。
现在,人们可能有几个月没有退出,所以依靠它可能不是一个好主意。
此外,如果他们在不关闭的情况下关闭机器,那么文件也不会被删除。
您可以使用文件系统观察程序监视您编写的文件,并等待一段时间不活动(10分钟,1小时,1天或任何时间),然后删除该文件。
但这对一切都不适用。某些程序可能具有“打开”文件,但可能没有锁定基础文件。如果发生这种情况,那么您将无法知道何时删除文件是安全的。
但是,我想你可能只是忽略了这个问题。大多数人可能都有过剩的硬盘空间,所以他们可能不会碰到它。如果他们这样做,我认为Windows弹出一个低磁盘空间对话框,让他们可以选择清除他们的临时目录,这将解决问题。
<强>更新强>
我认为Windows Update将每月重启用户的计算机一次,因此应该在发生这种情况时清除临时文件。
不能保证不存在问题,但在实践中我认为这应该是非常罕见的。
更新2:
通过评论提示,我去实际测试了这个,看起来Windows在用户退出时不会删除临时文件。但是,我仍然说在OP的情况下,这不是一个真正的问题。当它成为问题(因为磁盘空间不足)时,Windows将提示用户删除临时文件。
答案 5 :(得分:1)
在ASP.NET中使用临时文件时,请使用PAGE_DISPOSED事件删除您在页面中创建的所有临时文件。否则,您最终可能会争用在DISPOSED之前不会放弃的组件。
答案 6 :(得分:1)
我使用这个解决方案(非常可靠):
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();
在申请开始时。
答案 7 :(得分:0)
你可以创建一个临时文件,你可以在其中继续编写在进程中创建的文件名,在处理结束时你可以在操作结束后在Disponse方法中删除(前提条件 - 实现IDisposable和)已完成。
其他方式是写入独立进程,每隔一段时间执行一次清理。
在文件末尾附上日期,并在当天结束时删除该日期,并且进程将在结束时生成新文件。
divo tempfilecollection类给出了一个很好的建议。