我发现自己这么做只是为了确保文件名不被使用。有没有更好的办法?
Directory.Exists(name) || File.Exists(name)
当然:)
internal static bool FileOrDirectoryExists(string name)
{
return (Directory.Exists(name) || File.Exists(name));
}
请注意,您使用Exists()检查正在使用的文件或目录名称的事实受竞争条件的影响。
在Exists()测试通过后的任何时候,例如,在代码到达创建文件的位置之前,某些东西可能会创建一个具有该名称的文件。
(我假设文件已经存在是一个特例条件)。
简单地打开文件,指定适当的FileShare参数更可靠。
例:
using System;
using System.IO;
static class FileNameInUse
{
static void Main(string[] args)
{
string path = args[0];
using (var stream = File.Open(path, FileMode.CreateNew, FileAccess.Write, FileShare.None))
{
// Write to file
}
}
}
因此,简单地处理失败时的IOException可能会导致更简单的代码更不容易出现竞争条件,因为现在:
FileMode.CreateNew
将导致IOException
被抛出FileShare.None
,在关闭文件之前,没有其他进程可以访问该文件。不幸的是,如果没有一些丑陋的P / Invoke,就不可能检查文件当前是否正在使用,而不是抛出异常:
bool IsFileInUse(string fileName)
{
IntPtr hFile = Win32.CreateFile(fileName, Win32.FILE_READ_DATA, 0, IntPtr.Zero, Win32.OPEN_EXISTING, Win32.FILE_ATTRIBUTE_NORMAL, IntPtr.Zero);
if (hFile.ToInt32() == Win32.INVALID_HANDLE_VALUE)
return true;
Win32.CloseHandle(hFile);
return false;
}
class Win32
{
const uint FILE_READ_DATA = 0x0001;
const uint FILE_SHARE_NONE = 0x00000000;
const uint FILE_ATTRIBUTE_NORMAL = 0x00000080;
const uint OPEN_EXISTING = 3;
const int INVALID_HANDLE_VALUE = -1;
[DllImport("kernel32.dll", SetLastError=true)]
internal static extern IntPtr CreateFile(string lpFileName,
uint dwDesiredAccess,
uint dwShareMode,
IntPtr lpSecurityAttributes,
uint dwCreationDisposition,
uint dwFlagsAndAttributes,
IntPtr hTemplateFile);
[DllImport("kernel32.dll")]
internal static extern bool CloseHandle(IntPtr hObject);
}
这种快速检查也容易出现竞争条件,除非你从它返回文件句柄,并将其传递给相关的FileStream
构造函数。
我认为这是唯一的方法。我通常有一个“FileManager”类,它具有封装I / O方法的静态方法,包括你指定的方法,然后在所有应用程序中使用“FileManager”作为库。
另一种检查文件是否存在的方法。
FileInfo file = new FileInfo("file.txt");
if (file.Exists)
{
// TO DO
}
我检查这个的方法是使用FileSystemInfo,这是我的代码:
FileSystemInfo info =
File.GetAttributes(data.Path).HasFlag(FileAttributes.Directory) ?
new DirectoryInfo(data.Path) : (FileSystemInfo)new FileInfo(data.Path);
return info.Exists;
bool FileOrDirectoryExists(string path)
{
try
{
File.GetAttributes(_source);
}
catch (FileNotFoundException)
{
return false;
}
return true;
}