.NET File.Create,创建文件后无法删除文件

12
使用方法:System.IO.File.Create() 创建文件后,它仍然被进程使用,我无法删除它。 有什么更好的方法可以创建一个大小为0字节的文件,然后关闭和处理吗?

你正在使用 using (FileStream fs = File.Create("..")) 吗?(一旦进程退出,这并不重要)? - Chris S
当方法退出时,Dispose或Close会被调用吗? - Chris S
文档和智能感知明确表明Create方法返回一个FileStream - Cecil Has a Name
并不总是这样。您必须明确地执行此操作。在使用 C# 附加文件到电子邮件并未处置附件对象时,我曾经通过艰难的方式发现了这一点。但是,MailMessage 对象确实会“自动”处理处置。所以这很难说。 - Fandango68
6个回答

29

JL,

你应该使用 using 语句来包装你对 .Create 的调用,这样 .Create 返回的 FileStream 就能被正确地关闭。例如:

using (File.Create("path")){...}

谢谢,我觉得这个问题困扰了我多年...现在我知道了 :) - JL.
只有空的 - using (File.Create(binaryAddress + @"\LOG")) 是可以的吗? - JL.
4
为了更清晰明确,我建议使用显式的闭包来代替空的 using - wefwfwefwe
一个空的using可以工作,但是与仅仅关闭文件相比没有任何添加。 - Guffa

16
Create 方法不仅会创建文件,还会将其打开并返回一个 FileStream 对象,您可以使用该对象向文件写入内容。
您必须在自己使用完后关闭文件,否则它将不会在垃圾回收 FileStream 对象之前被关闭。
最简单的方法是使用 Create 方法返回的引用来关闭文件:
File.Create(fileName).Close();

12

nikmd23给出了简短的答案,长答案是:返回的FileStream没有被确定性地处理,因此当您尝试删除它时,它的文件句柄未关闭。

正如nikmd23所说,使用using语句包装您的File.Create(...)调用将确保流被关闭和处理:

using (FileStream fs = File.Create(path)) { 
  // do anything with the stream if need-be...
}
File.Delete(path); //after it's been disposed of.

using(...) 块只是编译器语法糖的一个简化表达:

FileStream fs = File.Create(path);
try { 
   // do anything with the stream if need-be...
}
finally { 
  fs.Dispose();
}
File.Delete(path)

不错的分析 @yoopergeek ;) - nikmd23
我有点觉得我在重复,但我还是喜欢知道一些额外的细节,并且想“为什么不分享呢?” 我也认为我应该避免深入实现/使用IDisposable... :D - Yoopergeek
你展示的代码与使用方式不等价。Create调用不是在try块内完成的,而是在之前完成的。如果你在using块内没有对文件做任何操作(正如OP解释他不会这样做),那么它与仅关闭文件没有任何区别。 - Guffa
1
够接近了。 ;) 与其只是抨击我,为什么不提供正确的代码呢?或者提供一个证明我错误的MSDN链接,例如:http://msdn.microsoft.com/en-us/library/yh598w02.aspx - Yoopergeek

1
using(FileStream f = File.Create(file_path))
{
  // ... do something with file
  f.Close();
}

"f.Close();"这行代码会立即关闭文件。如果不手动关闭,Disposing可能无法关闭它。


1
在什么情况下Dispose不会关闭文件?据我所知,它 总是 会关闭文件。 - John Saunders
也许是我的错误,但我尝试在使用()代码后使用File.Delete(),它向我抛出了拒绝异常。在放置f.Close()之后,它允许我立即删除文件。我认为这可能是GC问题,因此没有一个对象立即被销毁,只是标记为处置和资源,就像物理文件没有立即关闭一样。有人有什么想法吗? - Victor Gelmutdinov
1
不是垃圾回收器关闭文件,而是调用Dispose方法,进而调用Close方法,因此在using块的末尾调用Close是多余的。 - Guffa

1

在几乎所有情况下,您应该使用nikmd23的答案。如果您不能这样做,因为您需要将FileStream传递到其他地方,请确保最终调用FileStream.Close方法。最好的方法是让“拥有”FileStream的类本身实现IDisposable,并在其Dispose方法中关闭流。

有关实现IDisposable的更多信息,请参阅MSDN文档。更易读且更为实时的是Joe Duffy的文章


+1 链接到IDisposable信息。 在我看来,学习如何正确地实现IDisposable接口和模式是成为更好的.NET开发人员的最重要的里程碑之一。《框架设计指南》(书籍)也是关于实现IDisposable的良好资源。 - Yoopergeek

0

参见 System.IO.File.Create(String) 方法 的参数和返回值描述

参数

path 类型: System.String 要创建的文件的路径和名称。

返回值

类型: System.IO.FileStream

一个提供对指定路径中的文件进行读写访问的 FileStream

FileStream 的返回值用于对所创建的文件进行IO访问。如果您对新创建的文件不感兴趣(无论是写入还是读取),请关闭流。这就是 using 代码块确保的内容。


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