Archivo que está siendo utilizado por otro proceso después de usar File.Create ()

117

Estoy tratando de detectar si existe un archivo en tiempo de ejecución, si no, créelo. Sin embargo, recibo este error cuando intento escribir en él:

El proceso no puede acceder al archivo 'myfile.ext' porque está siendo utilizado por otro proceso.

string filePath = string.Format(@"{0}\M{1}.dat", ConfigurationManager.AppSettings["DirectoryPath"], costCentre); 
if (!File.Exists(filePath)) 
{ 
    File.Create(filePath); 
} 

using (StreamWriter sw = File.AppendText(filePath)) 
{ 
    //write my text 
}

¿Alguna idea de cómo arreglarlo?

Brett
fuente

Respuestas:

112

El File.Createmétodo crea el archivo y abre un FileStreamen el archivo. Entonces su archivo ya está abierto. Realmente no necesitas el método file.Create en absoluto:

string filePath = @"c:\somefilename.txt";
using (StreamWriter sw = new StreamWriter(filePath, true))
{
    //write to the file
}

El booleano en el StreamWriterconstructor hará que el contenido se agregue si el archivo existe.

Chris Dunaway
fuente
Probé el código anterior pero obtengo el mismo error cuando se crea el archivo y cuando intenta escribir en el archivo, muestra que otro proceso está utilizando el archivo.
Anmol Rathod
@AnmolRathod ¡asegúrate de no usar el File.Create()método! ¡El fragmento de arriba ya crea el archivo!
Daniel Eisenreich
138
    File.Create(FilePath).Close();
    File.WriteAllText(FileText);

Quiero actualizar esta respuesta para decir que esta no es realmente la forma más eficiente de escribir todo el texto. Solo debe usar este código si necesita algo rápido y sucio.

Yo era un programador joven cuando respondí a esta pregunta, y en ese entonces pensé que era una especie de genio para dar con esta respuesta.

Carsen Daniel Yates
fuente
4
Me encanta cómo todas las otras respuestas eran demasiado complicadas. La gente no se da cuenta de que existe una respuesta más sencilla a cada problema.
Carsen Daniel Yates
14
La desventaja de este código es que abre el archivo innecesariamente dos veces. Además, no es realmente necesario verificar si el archivo existe, ya que el constructor FileStream lo creará automáticamente por usted si no existe, a menos que le indique explícitamente que no lo haga.
reirab
2
@reirab Esto es completamente relativo. Necesito verificar si el archivo existe y, si lo hace, eliminarlo y crearlo nuevamente, por lo que esta respuesta es la preferida en mi caso.
makoshichi
1
@SO Entonces tienes un problema diferente al OP, solo uno relacionado. Además, en su caso, aún puede usar el FileStream(string, FileMode)constructor y pasarlo FileMode.Create , que sobrescribirá cualquier archivo existente. Todavía no es necesario abrir el archivo dos veces. Además, esta respuesta se editó después de que publiqué mi comentario original.
reirab
2
El objetivo de esta respuesta es mostrar que puede agregar .Close()al final, por lo que funciona en cualquier caso. Desconfío del sistema de uso FileStreampara todo porque no quiero que ocurra la excepción en el caso de FileMode.Createque el archivo ya esté allí, especialmente cuando quiero borrar el contenido y no agregarlo FileMode.Open. Para mí, FileStreamsolo funciona realmente después de deshacerse del archivo en cuestión y luego escribir en él. Dado que File.Createlo deja abierto y bloqueado, parece que agregarlo .Close()es la única forma real de lidiar con mi escenario y SO.
vapcguy
25

Al crear un archivo de texto, puede utilizar el siguiente código:

System.IO.File.WriteAllText("c:\test.txt", "all of your content here");

Usando el código de tu comentario. El archivo (flujo) que creó debe estar cerrado. File.Create devuelve el flujo de archivos al archivo recién creado:

string filePath = "filepath here";
if (!System.IO.File.Exists(filePath))
{
    System.IO.FileStream f = System.IO.File.Create(filePath);
    f.Close();
}
using (System.IO.StreamWriter sw = System.IO.File.AppendText(filePath))
{ 
    //write my text 
}
Ralf de Kleine
fuente
No parece que tenga una opción cercana. Aquí está el código: string filePath = string.Format (@ "{0} \ M {1} .dat", ConfigurationManager.AppSettings ["DirectoryPath"], costCentre); if (! File.Exists (filePath)) {File.Create (filePath); } using (StreamWriter sw = File.AppendText (filePath)) {// escribir mi texto}
Brett
File.Createregresa FileStreamy eso tieneClose()
Null Head
15
FileStream fs= File.Create(ConfigurationManager.AppSettings["file"]);
fs.Close();
user3430377
fuente
7
Bienvenido a Stackoverflow. Debería al menos escribir una descripción breve para describir su respuesta / solución.
Paresh Mayani
9

File.Create devuelve un FileStream. Debe cerrar eso cuando haya escrito en el archivo:

using (FileStream fs = File.Create(path, 1024)) 
        {
            Byte[] info = new UTF8Encoding(true).GetBytes("This is some text in the file.");
            // Add some information to the file.
            fs.Write(info, 0, info.Length);
        }

Puede utilizar using para cerrar automáticamente el archivo.

Kimtiede
fuente
Aunque el OP está tratando de abrir un StreamWritercomo se puede inferir de su uso de File.AppendText.
binki
8

Actualicé su pregunta con el fragmento de código. Después de una sangría adecuada, queda inmediatamente claro cuál es el problema: usa File.Create()pero no cierra el FileStreamque devuelve.

Hacerlo de esa manera es innecesario, StreamWriterya permite agregar a un archivo existente y crear un nuevo archivo si aún no existe. Me gusta esto:

  string filePath = string.Format(@"{0}\M{1}.dat", ConfigurationManager.AppSettings["DirectoryPath"], costCentre); 
  using (StreamWriter sw = new StreamWriter(filePath, true)) {
    //write my text 
  }

Que usa este StreamWriterconstructor .

Hans Passant
fuente
1

Esta pregunta ya ha sido respondida, pero aquí hay una solución del mundo real que verifica si el directorio existe y agrega un número al final si existe el archivo de texto. Utilizo esto para crear archivos de registro diarios en un servicio de Windows que escribí. Espero que esto ayude a alguien.

// How to create a log file with a sortable date and add numbering to it if it already exists.
public void CreateLogFile()
{
    // filePath usually comes from the App.config file. I've written the value explicitly here for demo purposes.
    var filePath = "C:\\Logs";

    // Append a backslash if one is not present at the end of the file path.
    if (!filePath.EndsWith("\\"))
    {
        filePath += "\\";
    }

    // Create the path if it doesn't exist.
    if (!Directory.Exists(filePath))
    {
        Directory.CreateDirectory(filePath);
    }

    // Create the file name with a calendar sortable date on the end.
    var now = DateTime.Now;
    filePath += string.Format("Daily Log [{0}-{1}-{2}].txt", now.Year, now.Month, now.Day);

    // Check if the file that is about to be created already exists. If so, append a number to the end.
    if (File.Exists(filePath))
    {
        var counter = 1;
        filePath = filePath.Replace(".txt", " (" + counter + ").txt");
        while (File.Exists(filePath))
        {
            filePath = filePath.Replace("(" + counter + ").txt", "(" + (counter + 1) + ").txt");
            counter++;
        }
    }

    // Note that after the file is created, the file stream is still open. It needs to be closed
    // once it is created if other methods need to access it.
    using (var file = File.Create(filePath))
    {
        file.Close();
    }
}
Martín pescador
fuente
1

Sé que esta es una pregunta antigua, pero solo quiero lanzar esto para que aún puedas usarlo File.Create("filename")", solo agregarlo .Dispose().

File.Create("filename").Dispose();

De esta forma crea y cierra el archivo para que el próximo proceso lo utilice.

Soy Batman
fuente
1
File.Create(FilePath).Close();de la respuesta anterior tiene this.Dispose(true); GC.SuppressFinalize((object) this);en su implementación.
Ghukas
1

Creo que conozco el motivo de esta excepción. Es posible que esté ejecutando este fragmento de código en varios subprocesos.

Kusala Subasinghe
fuente
Para mí fue el problema de que escribo un archivo de registro de manera asíncrona (en un hilo diferente: Task.Run () sin esperar (a propósito), y esto causa acceso de
varios
-1

Prueba esto: funciona en cualquier caso, si el archivo no existe, lo creará y luego escribirá en él. Y si ya existe, no hay problema, se abrirá y escribirá en él:

using (FileStream fs= new FileStream(@"File.txt",FileMode.Create,FileAccess.ReadWrite))
{ 
     fs.close();
}
using (StreamWriter sw = new StreamWriter(@"File.txt")) 
 { 
    sw.WriteLine("bla bla bla"); 
    sw.Close(); 
 } 
PureSilence
fuente
1
el uso cerrará el archivo mediante la llamada Dispose. En su archivo de muestra se cerró dos veces
Valentine Zakharenko