在C#中创建一个空文件

219

在C#/.NET中创建空文件的最简单和经典的方法是什么?

目前我所找到的最简单的方法是:

System.IO.File.WriteAllLines(filename, new string[0]);
7个回答

441

仅使用File.Create会使文件保持打开状态,这可能不是您想要的。

您可以使用以下代码:

// Results in compiler warning "warning CS0642: Possible mistaken empty statement"
using (File.Create(filename)) ;

看起来有点奇怪,不过也可以使用大括号:

using (File.Create(filename)) {}

或者直接调用Dispose

File.Create(filename).Dispose();

无论如何,如果您要在多个地方使用它,您应该考虑将其包装在一个帮助方法中,例如:

public static void CreateEmptyFile(string filename)
{
    File.Create(filename).Dispose();
}

请注意,直接调用Dispose而不是使用using语句在这里并没有什么区别,据我所知 - 它唯一可能有区别的方式是如果在线程调用File.Create和调用Dispose之间中止。如果存在这种竞争条件,我认为它也会存在于using版本中,如果线程在File.Create方法的最后被中止,就在值返回之前...


8
有趣,我刚刚写了相同的代码大约5分钟前。我使用了"File.Create(filename).Close();",和你的代码差不多。 - Brian Genisio
2
我的代码使用了 using (File.Create(filename)) ;,但我喜欢 File.Create(filename).Dispose(); 的简洁性。 - Vadim
2
@user3791372:Close()也会释放资源。Close()只是调用Dispose - 请参见https://github.com/dotnet/coreclr/blob/master/src/mscorlib/src/System/IO/Stream.cs#L234 - Jon Skeet
3
如果文件已经存在且不是只读的,文件内容将被覆盖可能不太明显。为避免这种情况,使用 using (new FileStream(filename, FileMode.CreateNew)) { } - Phil Haselden
1
@huha:没有任何迹象表明 OP 捕获任何这样的异常。我知道我经常编写期望能够创建文件的工具,我希望该异常只传播到顶层。 - Jon Skeet
显示剩余6条评论

42
File.WriteAllText("path", String.Empty);
或者
File.CreateText("path").Close();

4
使用第一个选项,文件长度为3字节:编码代码。使用第二个选项,文件长度为0字节(真正的空文件)。 - Fil
1
@Fil:你确定吗?文档File.WriteAllText(string, string)使用“UTF-8编码没有字节顺序标记(BOM)”。如果你仍然看到一个,那可能是WriteAllText或其文档中值得报告的错误。 - Heinzi
我记得我试过了。也许这是以前 .Net 版本的一个旧 bug?如果我明确指定使用 UTF8 编码(或 Unicode 或其他编码),那么文件就不为空:<File.WriteAllText("c:\del.txt", String.Empty, System.Text.Encoding.UTF8);> - Fil
2
@Fil,Encoding.UTF8返回一个输出字节顺序标记(BOM)的编码器。您可以使用new UTF8Encoding(false)来获取一个不输出BOM的UTF8编码器。 - Daniel Crabtree
1
不知道 WriteAllText 在之前的 .NET 版本中是否真的有所不同。然而,为了更加保险,只需跳过编码部分并使用 File.WriteAllBytes(path, new byte[] { }); 即可。 - Jürgen Steinblock

22
System.IO.File.Create(@"C:\Temp.txt");

正如其他人所指出的,你应该处理这个对象或将其包装在一个空的using语句中。

using (System.IO.File.Create(@"C:\Temp.txt"));

5
不会更好地处理对象吗? 例如: 使用(System.IO.File.Create(filepath)){ } - kentaromiura
@kentaromiura:我的想法完全一样,因此我回答了这个问题 :) - Jon Skeet

8
为了避免意外覆盖已有文件,请使用以下方法:
using (new FileStream(filename, FileMode.CreateNew)) {}

...并处理IOException,如果文件已经存在会发生该异常。

File.Create在其他回答中被建议使用,如果文件已经存在,它将覆盖文件内容。在简单的情况下,您可以使用File.Exists()来缓解这个问题。然而,在多个线程和/或进程同时尝试创建同一个文件夹中的文件的情况下,需要更健壮的解决方案。


1
同意,执行 if (!File.Exists(file)) // then create file 是许多开发人员遵循的反模式。最好执行创建并捕获任何异常,从而使您的代码更加线程安全。 - bytedev

4
您可以链式调用返回的对象,这样您就可以在一个语句中立即关闭您刚刚打开的文件。
File.Open("filename", FileMode.Create).Close();

3
创建空文件的一个常见用例是在不需要更复杂的进程间通信的情况下触发另一个进程中发生的操作。在这种情况下,从外部世界的角度来看,文件创建可以帮助实现原子性(特别是如果要删除文件以“消耗”触发器)。
因此,在要创建文件的相同目录中创建一个垃圾名称(Guid.NewGuid.ToString()),然后从临时名称移动到所需名称可能会有所帮助。否则,检查文件存在并删除触发器的触发代码可能会遇到竞争条件,其中文件在完全关闭之前被删除。
将临时文件放在相同的目录(和文件系统)中可以为您提供所需的原子性。这类似于以下内容。
public void CreateEmptyFile(string path)
{
    string tempFilePath = Path.Combine(Path.GetDirectoryName(path),
        Guid.NewGuid.ToString());
    using (File.Create(tempFilePath)) {}
    File.Move(tempFilePath, path);
}

0

Path.GetTempFileName()会创建一个唯一命名的空文件并返回其路径。

如果您想控制路径但获取随机文件名,可以使用GetRandomFileName仅返回文件名字符串,并将其与Create一起使用

例如:

string fileName=Path.GetRandomFileName();
File.Create("custom\\path\\" + fileName);

在我看来,GetTempFileName() 的命名完全不准确。 - kay.herzam
为什么这个答案不太有用呢? - Crippledsmurf
6
有两个原因使得这种做法没有帮助:1. 问题并没有询问如何生成随机文件名,所以这会分散注意力。2. 文件没有被关闭,这意味着如果你稍后尝试打开另一个文件写入器或移动该文件,操作将失败。 - River Satya
我理解你的观点,但是:
  1. 所有文件都需要一个名称。那只是一种简单方便的方式,可以获得一个不太可能与其他内容冲突的名称。
  2. 问题是关于创建文件的,而相关代码最少确实完成了文件的创建,因此为了简单起见并保持回答与问题的焦点,我省略了之后对文件的管理部分。
- Crippledsmurf

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接