2010-04-23 38 views
7

Estoy intentando descargar un archivo desde la web y guardarlo localmente, pero me da una excepción:C Excepción archivo #: no tiene acceso al archivo porque está siendo utilizado por otro proceso

C# El proceso no se puede acceder al archivo 'blah' porque está siendo utilizado por otro proceso.

Este es mi código:

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

que he visto muchas otras preguntas con la misma excepción, pero ninguno de ellos parecen aplicarse aquí. ¿Alguna ayuda?

Actualización:
¡Gracias por las respuestas! Eliminar el File.Create(...) lo arregló!

Un comentario sobre la documentación de OpenWrite: es un poco engañoso, la breve descripción dice:

Abre un archivo existente para la escritura.

La descripción detallada dice:

Si el archivo existe, se abre para escrito al principio. El archivo existente no está truncado.

Actualización 2.0:
Parece que la discrepancia entre IntelliSense/F1 y la documentación en línea. Pensé que debería ser el mismo ya que permití que F1 se conectara a la web cuando mostraba documentación.

+0

¿Por qué necesita File.Create ("data.csv") si está utilizando File.OpenWrite ("data.csv")? – systempuntoout

+0

@systempuntoout Debido a una documentación incorrecta ... "Abre un archivo existente para escribir". Eso me hizo asumir que tenía que crear el archivo antes de intentar usar el método. – Kiril

Respuesta

17

File.Create devuelve FileStream - que no está cerrando. Eso significa que no podrá abrir otra secuencia escribiendo en el mismo archivo hasta que el finalizador haya cerrado la transmisión existente.

Simplemente deshacerse de la llamada a File.Create - File.OpenWrite lo creará de todos modos. Por otra parte, mantener el FileStream alrededor de escribir a:

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

Tenga en cuenta que también estoy disponiendo del WebResponse aquí, lo que usted debe hacer para asegurarse de que la conexión se libera a la agrupación de conexiones.

+0

@Jon, gracias que funcionó ... Me confundí debido a la documentación: "** Si el archivo existe **, se abre para escribir al principio. El archivo existente no se trunca". – Kiril

+0

@Lirik: está abierto de cualquier manera, pero el hecho de que no esté truncado es desagradable, no lo había visto. En ese caso, * probablemente * quiera usar 'File.Create' pero se deshaga de la llamada' File.OpenWrite'; el código que he incluido en la respuesta debería estar bien. –

+0

@Jon gracias ... ¿Tiene algún comentario sobre la documentación de OpenWrite? Parece que no está claro. – Kiril

3

Primero. File.Create devolverá una secuencia que debe usar para acceder al archivo.

En segundo lugar, si eso no resuelve el problema, si google who lock encontrará un programa que le permite determinar qué proceso está accediendo a un archivo al mismo tiempo.

4

El problema es que el método File.Create realidad abre el archivo y vuelve un objeto FileStream. No cerrará el archivo hasta que el objeto sea basura recolectada (lo que ocurrirá en un tiempo indeterminado). El objeto FileStream aún se crea, independientemente de si lo usa o no. Pruebe esto:

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