Kiril
Kiril

Reputation: 40345

C# File Exception: cannot access the file because it is being used by another process

I'm trying to download a file from the web and save it locally, but I get an exception:

C# The process cannot access the file 'blah' because it is being used by another process.

This is my code:

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);
}

I've seen numerous other questions with the same exception, but none of them seem to apply here. Any help?

Update:
Thanks for the answers! Removing the File.Create(...) fixed it!

One comment on the documentation of OpenWrite: it is a little misleading, the brief description says:

Opens an existing file for writing.

The detailed description says:

If the file exists, it is opened for writing at the beginning. The existing file is not truncated.

Update 2.0:
It looks like the discrepancy is between IntelliSense/F1 and the online documentation. I thought it should be the same since I allow F1 to connect to the web when it's displaying documentation.

Upvotes: 7

Views: 6705

Answers (4)

Peter Ruderman
Peter Ruderman

Reputation: 12485

The problem is that the File.Create method actually opens the file and returns a FileStream object. It won't close the file until the object is garbage collected (which will happen at an indeterminate time). The FileStream object still gets created, regardless of whether or not you use it. Try this:

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

Upvotes: 4

house9
house9

Reputation: 20614

looks like File.Create returns an open FileStream object

http://msdn.microsoft.com/en-us/library/aa328775(v=VS.71).aspx

try

using (FileStream fs = File.Create("data.csv"))

and leave off the first File.Create

Upvotes: 6

AaronLS
AaronLS

Reputation: 38367

First. File.Create will return a stream that you should use for accessing the file.

Second, if that doesn't resolve the issue, if you google who lock you will find a program that let's you determine what process is accessing a file at the same time.

Upvotes: 3

Jon Skeet
Jon Skeet

Reputation: 1500514

File.Create returns a FileStream - which you're not closing. That means you won't be able to open another stream writing to the same file until the finalizer has closed the existing stream.

Just get rid of the call to File.Create - File.OpenWrite will create it anyway. Alternatively, keep the FileStream around to write to:

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);
    }
}

Note that I'm also disposing of the WebResponse here, which you should do to make sure the connection is freed to the connection pool.

Upvotes: 18

Related Questions