在尝试回答this question时,我惊讶地发现,当该文件已经存在时尝试创建新文件不会抛出唯一的异常类型,它只会抛出一个通用的IOException
。 / p>
因此,我想知道如何确定IOException
是现有文件的结果还是其他一些IO错误。
该异常有一个HResult,但此属性受到保护,因此对我无法使用。
我能看到的另一种方式是模式匹配感觉糟糕的消息字符串。
示例:
try
{
using (var stream = new FileStream("C:\\Test.txt", FileMode.CreateNew))
using (var writer = new StreamWriter(stream))
{
//write file
}
}
catch (IOException e)
{
//how do I know this is because a file exists?
}
答案 0 :(得分:9)
try
{
using (var stream = new FileStream("C:\\Test.txt", FileMode.CreateNew))
using (var writer = new StreamWriter(stream))
{
//write file
}
}
catch (IOException e)
{
var exists = File.Exists(@"C:\Text.text"); // =)
}
不适用于可能已被删除的临时文件等。
答案 1 :(得分:5)
您可以将此条件放在IOException的catch语句中:if(ex.Message.Contains("already exists")) { ... }
。这是一个hack,但它适用于文件存在的所有情况,甚至是临时文件等。
答案 2 :(得分:4)
当您尝试创建新文件并且它已经存在时,IOException将具有Hresult = 0x80070050 (-2147024816)
。
所以你的代码看起来像这样:
try
{
using (var stream = new FileStream("C:\\Test.txt", FileMode.CreateNew))
using (var writer = new StreamWriter(stream))
{
//write file
}
}
catch (IOException e)
{
if (e.HResult == -2147024816)
{
// File already exists.
}
}
答案 3 :(得分:2)
要修改@jgauffin,在C#6中,您可以使用File.Exists
子句中的when
来避免输入catch
块,从而behaving more like an actual dedicated exception:
try
{
using (var stream = new FileStream("C:\\Test.txt", FileMode.CreateNew))
using (var writer = new StreamWriter(stream))
{
//write file
}
}
catch (IOException e) when (File.Exists(@"C:\Text.text"))
{
//...
}
答案 4 :(得分:0)
你应该使用
FileMode.Create
而不是
FileMode.CreateNew
如果文件已存在,它将覆盖该文件。
答案 5 :(得分:0)
你做不到。不幸的是,由于我在.NET框架中理解的原因,没有进一步指定IOExceptions。
但是在创建新文件的情况下,通常的做法是先检查文件是否存在。像这样:
try
{
if (File.Exists("C:\\Test.txt"))
{
//write file
using (var stream = new FileStream("C:\\Test.txt", FileMode.CreateNew))
using (var writer = new StreamWriter(stream))
{
//The actual writing of file
}
}
}
catch (IOException ex)
{
//how do I know this is because a file exists?
Debug.Print(ex.Message);
}
也许不是你想要的答案。但是,c'est ca。
答案 6 :(得分:0)
这不是100%万无一失(IOException有其他原因),但您至少可以排除所有派生的异常类型:
try
{
...
}
catch(IOException e)
{
if (e is UnauthorizedAccessException) throw;
if (e is DirectoryNotFoundException) throw;
if (e is PathTooLongException) throw;
// etc for other exceptions derived from IOException
... assume file exists
}
或同等的:
try
{
...
}
catch(UnauthorizedAccessException)
{
throw;
}
catch(DirectoryNotFoundException)
{
throw;
}
catch(PathTooLongException)
{
throw;
}
catch(IOException e)
{
... assume file exists
}
关于链接的问题,我只是检查是否存在,提示用户覆盖,然后使用OpenOrCreate
覆盖它是否存在。我认为大多数应用程序都是以这种方式工作的,即使存在覆盖在错误时刻创建的文件的理论风险。
答案 7 :(得分:0)
在C#6和更高版本中:
const int WARN_WIN32_FILE_EXISTS = unchecked((int)0x80070050);
try
{
...
}
catch (IOException e) when (e.HResult == WARN_WIN32_FILE_EXISTS)
{
...
}
...或when (e.HResult == -2147024816)
,如果您要“快速而不可穿透”。 ;-)
(FWIW,Mono忠实地复制了以Windows为中心的错误代码,并且在Mac / Linux上也可以使用。)