使用.net框架,您可以选择使用
创建临时文件Path.GetTempFileName();
MSDN没有告诉我们临时文件会发生什么。我记得在某个地方读到它们在重启时会被操作系统删除。这是真的吗?
如果操作系统没有删除文件,为什么它们被称为临时文件?它们是普通目录中的普通文件。
答案 0 :(得分:42)
简短的回答:它们不会被删除。
答案很长:
托管Path.GetTempFileName()
方法调用本机Win32API GetTempFileName()
方法,如下所示:
//actual .NET 2.0 decompiled code
// .NET Reflector rocks for looking at plumbing
public static string GetTempFileName()
{
string tempPath = GetTempPath();
new FileIOPermission(FileIOPermissionAccess.Write, tempPath).Demand();
StringBuilder tmpFileName = new StringBuilder(260);
if (Win32Native.GetTempFileName(tempPath, "tmp", 0, tmpFileName) == 0)
{
__Error.WinIOError();
}
return tmpFileName.ToString();
}
本机方法的文档说明:
不会自动删除其名称由此函数创建的临时文件。要删除这些文件,请调用DeleteFile。
我找到了一篇名为"Those pesky temp files"(2007年10月存档)的精彩文章,该文章从基础知识开始,触及处理临时文件的一些不太明显的问题,例如:
FileOption.DeleteOnClose
并让内核处理它)FileAttributes.Temporary
)文章中的C#代码:
using System;
using System.IO;
using System.Security.Permissions;
using System.Security.Principal;
using System.Security.AccessControl;
public static class PathUtility
{
private const int defaultBufferSize = 0x1000; // 4KB
#region GetSecureDeleteOnCloseTempFileStream
/// <summary>
/// Creates a unique, randomly named, secure, zero-byte temporary file on disk, which is automatically deleted when it is no longer in use. Returns the opened file stream.
/// </summary>
/// <remarks>
/// <para>The generated file name is a cryptographically strong, random string. The file name is guaranteed to be unique to the system's temporary folder.</para>
/// <para>The <see cref="GetSecureDeleteOnCloseTempFileStream"/> method will raise an <see cref="IOException"/> if no unique temporary file name is available. Although this is possible, it is highly improbable. To resolve this error, delete all uneeded temporary files.</para>
/// <para>The file is created as a zero-byte file in the system's temporary folder.</para>
/// <para>The file owner is set to the current user. The file security permissions grant full control to the current user only.</para>
/// <para>The file sharing is set to none.</para>
/// <para>The file is marked as a temporary file. File systems avoid writing data back to mass storage if sufficient cache memory is available, because an application deletes a temporary file after a handle is closed. In that case, the system can entirely avoid writing the data. Otherwise, the data is written after the handle is closed.</para>
/// <para>The system deletes the file immediately after it is closed or the <see cref="FileStream"/> is finalized.</para>
/// </remarks>
/// <returns>The opened <see cref="FileStream"/> object.</returns>
public static FileStream GetSecureDeleteOnCloseTempFileStream()
{
return GetSecureDeleteOnCloseTempFileStream(defaultBufferSize, FileOptions.DeleteOnClose);
}
/// <summary>
/// Creates a unique, randomly named, secure, zero-byte temporary file on disk, which is automatically deleted when it is no longer in use. Returns the opened file stream with the specified buffer size.
/// </summary>
/// <remarks>
/// <para>The generated file name is a cryptographically strong, random string. The file name is guaranteed to be unique to the system's temporary folder.</para>
/// <para>The <see cref="GetSecureDeleteOnCloseTempFileStream"/> method will raise an <see cref="IOException"/> if no unique temporary file name is available. Although this is possible, it is highly improbable. To resolve this error, delete all uneeded temporary files.</para>
/// <para>The file is created as a zero-byte file in the system's temporary folder.</para>
/// <para>The file owner is set to the current user. The file security permissions grant full control to the current user only.</para>
/// <para>The file sharing is set to none.</para>
/// <para>The file is marked as a temporary file. File systems avoid writing data back to mass storage if sufficient cache memory is available, because an application deletes a temporary file after a handle is closed. In that case, the system can entirely avoid writing the data. Otherwise, the data is written after the handle is closed.</para>
/// <para>The system deletes the file immediately after it is closed or the <see cref="FileStream"/> is finalized.</para>
/// </remarks>
/// <param name="bufferSize">A positive <see cref="Int32"/> value greater than 0 indicating the buffer size.</param>
/// <returns>The opened <see cref="FileStream"/> object.</returns>
public static FileStream GetSecureDeleteOnCloseTempFileStream(int bufferSize)
{
return GetSecureDeleteOnCloseTempFileStream(bufferSize, FileOptions.DeleteOnClose);
}
/// <summary>
/// Creates a unique, randomly named, secure, zero-byte temporary file on disk, which is automatically deleted when it is no longer in use. Returns the opened file stream with the specified buffer size and file options.
/// </summary>
/// <remarks>
/// <para>The generated file name is a cryptographically strong, random string. The file name is guaranteed to be unique to the system's temporary folder.</para>
/// <para>The <see cref="GetSecureDeleteOnCloseTempFileStream"/> method will raise an <see cref="IOException"/> if no unique temporary file name is available. Although this is possible, it is highly improbable. To resolve this error, delete all uneeded temporary files.</para>
/// <para>The file is created as a zero-byte file in the system's temporary folder.</para>
/// <para>The file owner is set to the current user. The file security permissions grant full control to the current user only.</para>
/// <para>The file sharing is set to none.</para>
/// <para>The file is marked as a temporary file. File systems avoid writing data back to mass storage if sufficient cache memory is available, because an application deletes a temporary file after a handle is closed. In that case, the system can entirely avoid writing the data. Otherwise, the data is written after the handle is closed.</para>
/// <para>The system deletes the file immediately after it is closed or the <see cref="FileStream"/> is finalized.</para>
/// <para>Use the <paramref name="options"/> parameter to specify additional file options. You can specify <see cref="FileOptions.Encrypted"/> to encrypt the file contents using the current user account. Specify <see cref="FileOptions.Asynchronous"/> to enable overlapped I/O when using asynchronous reads and writes.</para>
/// </remarks>
/// <param name="bufferSize">A positive <see cref="Int32"/> value greater than 0 indicating the buffer size.</param>
/// <param name="options">A <see cref="FileOptions"/> value that specifies additional file options.</param>
/// <returns>The opened <see cref="FileStream"/> object.</returns>
public static FileStream GetSecureDeleteOnCloseTempFileStream(int bufferSize, FileOptions options)
{
FileStream fs = GetSecureFileStream(Path.GetTempPath(), bufferSize, options | FileOptions.DeleteOnClose);
File.SetAttributes(fs.Name, File.GetAttributes(fs.Name) | FileAttributes.Temporary);
return fs;
}
#endregion
#region GetSecureTempFileStream
public static FileStream GetSecureTempFileStream()
{
return GetSecureTempFileStream(defaultBufferSize, FileOptions.None);
}
public static FileStream GetSecureTempFileStream(int bufferSize)
{
return GetSecureTempFileStream(bufferSize, FileOptions.None);
}
public static FileStream GetSecureTempFileStream(int bufferSize, FileOptions options)
{
FileStream fs = GetSecureFileStream(Path.GetTempPath(), bufferSize, options);
File.SetAttributes(fs.Name, File.GetAttributes(fs.Name) | FileAttributes.NotContentIndexed | FileAttributes.Temporary);
return fs;
}
#endregion
#region GetSecureTempFileName
public static string GetSecureTempFileName()
{
return GetSecureTempFileName(false);
}
public static string GetSecureTempFileName(bool encrypted)
{
using (FileStream fs = GetSecureFileStream(Path.GetTempPath(), defaultBufferSize, encrypted ? FileOptions.Encrypted : FileOptions.None))
{
File.SetAttributes(fs.Name, File.GetAttributes(fs.Name) | FileAttributes.NotContentIndexed | FileAttributes.Temporary);
return fs.Name;
}
}
#endregion
#region GetSecureFileName
public static string GetSecureFileName(string path)
{
return GetSecureFileName(path, false);
}
public static string GetSecureFileName(string path, bool encrypted)
{
using (FileStream fs = GetSecureFileStream(path, defaultBufferSize, encrypted ? FileOptions.Encrypted : FileOptions.None))
{
return fs.Name;
}
}
#endregion
#region GetSecureFileStream
public static FileStream GetSecureFileStream(string path)
{
return GetSecureFileStream(path, defaultBufferSize, FileOptions.None);
}
public static FileStream GetSecureFileStream(string path, int bufferSize)
{
return GetSecureFileStream(path, bufferSize, FileOptions.None);
}
public static FileStream GetSecureFileStream(string path, int bufferSize, FileOptions options)
{
if (path == null)
throw new ArgumentNullException("path");
if (bufferSize <= 0)
throw new ArgumentOutOfRangeException("bufferSize");
if ((options & ~(FileOptions.Asynchronous | FileOptions.DeleteOnClose | FileOptions.Encrypted | FileOptions.RandomAccess | FileOptions.SequentialScan | FileOptions.WriteThrough)) != FileOptions.None)
throw new ArgumentOutOfRangeException("options");
new FileIOPermission(FileIOPermissionAccess.Write, path).Demand();
SecurityIdentifier user = WindowsIdentity.GetCurrent().User;
FileSecurity fileSecurity = new FileSecurity();
fileSecurity.AddAccessRule(new FileSystemAccessRule(user, FileSystemRights.FullControl, AccessControlType.Allow));
fileSecurity.SetAccessRuleProtection(true, false);
fileSecurity.SetOwner(user);
// Attempt to create a unique file three times before giving up.
// It is highly improbable that there will ever be a name clash,
// therefore we do not check to see if the file first exists.
for (int attempt = 0; attempt < 3; attempt++)
{
try
{
return new FileStream(Path.Combine(path, Path.GetRandomFileName()),
FileMode.CreateNew, FileSystemRights.FullControl,
FileShare.None, bufferSize, options, fileSecurity);
}
catch (IOException)
{
if (attempt == 2)
throw;
}
}
// This code can never be reached.
// The compiler thinks otherwise.
throw new IOException();
}
#endregion
}
答案 1 :(得分:8)
根据我的%tmp%中的March文件,我会说不是。
为什么他们被称为临时 - 因为这是他们的预期用法。它们不是系统文件;它们不是应用程序文件,它们不是用户文档......它们只是为了允许应用程序进行临时处理(可能是大量数据),或者经常通过IPC将数据传递到另一个进程。因此,他们确实是暂时的。
你的目标应该是删除你创建的任何临时文件,致命的“杀死”等等。我经常使用“使用” - 我创建了一个包装类 - 即。
sealed class TempFile : IDisposable { // formatted for space
string path;
public string Path {
get {
if(path==null) throw new ObjectDisposedException(GetType().Name);
return path;
}
}
public TempFile() : this(System.IO.Path.GetTempFileName()) { }
public TempFile(string path) {
if (string.IsNullOrEmpty(path)) throw new ArgumentNullException("path");
this.path = path;
}
private void Dispose(bool disposing) {
if (path != null) {
try {
File.Delete(path);
} catch { } // best endeavours...
path = null;
}
}
public void Dispose() {
GC.SuppressFinalize(this);
Dispose(true);
}
~TempFile() {
Dispose(false);
}
}
答案 2 :(得分:5)
有一个 FileOptions.DeleteOnClose 选项可能会执行您想要的操作。
以下是MSDN页面的链接。
答案 3 :(得分:1)
不,这不是真的。基本上,您的应用程序负责清理自己的混乱。如果不这样做,临时文件会随着时间累积。
答案 4 :(得分:0)
不,软件(读取:开发人员)负责创建一个临时文件来处理它。
查看您自己的临时文件夹,看看它的效果如何; - )
答案 5 :(得分:0)
它们被称为临时的,因为在大多数情况下,用户可以假设她可以安全地清理临时目录中的混乱......如果不是,通常情况下,这些文件都会被锁定。
一般来说,这些文件应该是短暂的:创建它们,将它们用于任何你需要的东西,当场删除它们。更糟糕的是,在退出应用程序时删除它们。
有时,你不能,例如。存档管理器或VCS允许使用编辑器(或差异查看器等)查看文件,但在编辑器之前关闭(或者无法监视生成的进程...)。
答案 6 :(得分:-2)
我很多时候在互联网上读过人们不想使用Path.GetTempFileName
,因为他们说它可能会返回一个已经存在的文件,以解决你可以根据一个文件建立文件名的问题GUID。
此函数解决了这个问题:迭代直到找到具有特定扩展名的不存在的文件名。
VB.net
Public Shared Function GetTempFileName(ByVal extensionWithDot As String) As String
Dim tempFileName As String
Do
tempFileName = System.IO.Path.GetTempFileName
If extensionWithDot IsNot Nothing Then
tempFileName = tempFileName.Replace(System.IO.Path.GetExtension(tempFileName), extensionWithDot)
End If
Loop While System.IO.File.Exists(tempFileName)
Return tempFileName
End Function
C#:
public static string GetTempFileName(string extensionWithDot)
{
string tempFileName = null;
do {
tempFileName = System.IO.Path.GetTempFileName;
if (extensionWithDot != null) {
tempFileName = tempFileName.Replace(System.IO.Path.GetExtension(tempFileName), extensionWithDot);
}
} while (System.IO.File.Exists(tempFileName));
return tempFileName;
}
注意:我使用参数extensionWithDot,因为System.IO.Path.GetExtension返回点。