使用.NET Framework,你必须创建临时文件与Windows临时文件行为 - 它们是否被系统删除?
Path.GetTempFileName();
的MSDN没有告诉我们发生了什么临时文件的选项。我记得在某个地方,当它重新启动时,它们被操作系统删除。这是真的?
如果文件没有被操作系统删除,为什么他们被称为临时?它们是普通目录中的普通文件。
使用.NET Framework,你必须创建临时文件与Windows临时文件行为 - 它们是否被系统删除?
Path.GetTempFileName();
的MSDN没有告诉我们发生了什么临时文件的选项。我记得在某个地方,当它重新启动时,它们被操作系统删除。这是真的?
如果文件没有被操作系统删除,为什么他们被称为临时?它们是普通目录中的普通文件。
简短的回答:他们不会被删除。
长的答案: 托管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
}
不,这是不正确的。基本上,你的应用程序负责清理自己的混乱。如果你不这样做,临时文件会随着时间而积累。
基于我的%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);
}
}
不,这在于软件的责任(阅读:开发商),创建一个临时文件来处理它。
有在自己的临时文件夹看看,看看如何好,工程;-)
有一个FileOptions.DeleteOnClose选项,可能会做你想要什么。
这里是链接到MSDN页面。
他们被称为临时的,因为在大多数情况下,用户可以假定她可以安全地清理临时区域中的垃圾......如果没有,一般来说,这些文件无论如何都是锁定的。
通常,这些文件应该是短暂的:创建它们,将它们用于任何需要的位置,然后当场删除它们。更糟的是,在退出应用程序时将其删除。
有时,你不能,例如。一个档案管理器或VCS允许用编辑器(或差异查看器等)查看文件,但在编辑器之前关闭(或不能监视产生的过程...)。
我已经在互联网上读了很多次,人们不希望使用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与点返回。
请检查您的英语。 – 2009-11-26 16:09:06
我很挑剔这里,但不应该`File.Delete`被移出和之前的空检查,并且空检查本身被替换为`disposing`检查? `尝试{File.Delete(path); } catch {} if(disposing){path = null;当然,它不是以任何方式改变结果。 – Stijn 2017-07-31 08:59:39