C#文件异常:无法访问文件,因为它正在被另一个进程使用。

7
我正在尝试从Web下载文件并将其保存在本地,但是我遇到了一个异常:

C#进程无法访问文件“blah”,因为它正在被另一个进程使用。

这是我的代码:

File.Create("data.csv");  // create the file
request = (HttpWebRequest)WebRequest.CreateDefault(new Uri(url));
request.Timeout = 30000;
response = (HttpWebResponse)request.GetResponse();

using (Stream file = File.OpenWrite("data.csv"), // <-- Exception here
    input = response.GetResponseStream())
{
    // Save the file using Jon Skeet's CopyStream method
    CopyStream(input, file);
}

我看到许多其他问题都有相同的异常,但似乎都不适用于此处。有任何帮助吗?

更新:
谢谢回答!删除File.Create(...)就解决了问题!

关于OpenWrite的文档,我想提一下:它有点误导人,简要说明如下:

打开一个现有的文件以进行写入。

详细说明如下:

如果文件存在,则在开头打开该文件进行写入。现有文件不会被截断。

更新2.0:
看起来这个差异是在IntelliSense / F1和在线文档之间的。我认为它应该是相同的,因为我允许F1在显示文档时连接到网络。


如果你使用File.OpenWrite("data.csv"),为什么还需要File.Create("data.csv")呢? - systempuntoout
由于文档不好,让我误解了“打开现有文件进行写入”的意思。这使我以为在使用该方法之前必须先创建文件。@systempuntoout - Kiril
4个回答

18

File.Create 返回一个 FileStream - 你没有关闭它。这意味着在终结器关闭现有流之前,您将无法打开另一个写入同一文件的流。

只需摆脱对 File.Create 的调用 - File.OpenWrite 将自动创建它。或者保留 FileStream 进行写入:

using (Stream file = File.Create("data.csv"))
{
    request = (HttpWebRequest)WebRequest.CreateDefault(new Uri(url));
    request.Timeout = 30000;
    using (var response = (HttpWebResponse)request.GetResponse())
    using (Stream input = response.GetResponseStream())
    {
        // Save the file using Jon Skeet's CopyStream method
        CopyStream(input, file);
    }
}

请注意,我在这里还处理了WebResponse,您应该这样做以确保连接被释放到连接池中。


@Jon,谢谢,那个方法可行...我之前被文档搞糊涂了:“如果文件存在,则在开头打开它进行写入。现有的文件不会被截断。” - Kiril
@Lirik:无论哪种方式打开都可以,但它没有被截断的事实很恶心,我没有注意到。在这种情况下,您可能想使用File.Create,但要摆脱File.OpenWrite调用-我在答案中包含的代码应该没问题。 - Jon Skeet
@Jon 谢谢你... 你对 OpenWrite 的文档有什么评论吗?似乎有些不太清楚。 - Kiril
@Jon 顺便说一下,我使用 IntelliSense 得到了同样(不完整)的文档。 - Kiril
@Lirik 关于F1文档的奇怪之处在于,它可能会提供包含错误的旧版本文档;也可能会给你一个与你所针对的.NET框架版本不符的文档;还有可能会给你同名函数在不同对象中的文档。在.NET中,不止一个类可以有一个OpenWrite函数。在F1文档中有一个下拉菜单,允许你从所有实现该函数名称的选项中选择你想要的那个。但是,它似乎不能根据F1的上下文智能地进行选择。 - AaronLS
显示剩余2条评论

6

4
问题在于File.Create方法实际上会打开文件并返回一个FileStream对象。它只有在对象被垃圾回收时才会关闭文件(这个时间不确定)。无论你是否使用它,FileStream对象仍然会被创建。请尝试以下操作:
using (Stream file = File.Create("data.csv"),
    input = response.GetResponseStream()) 
{ 
    // Save the file using Jon Skeet's CopyStream method 
    CopyStream(input, file); 
} 

3

首先,File.Create将返回一个流,您应该使用它来访问文件。

其次,如果这不能解决问题,如果你google who lock,你会找到一个程序,可以让你确定哪个进程同时访问一个文件。


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