Cree un archivo .txt si no existe y si agrega una nueva línea

161

Me gustaría crear un archivo .txt y escribirle, y si el archivo ya existe, solo quiero agregar algunas líneas más:

string path = @"E:\AppServ\Example.txt";
if (!File.Exists(path))
{
    File.Create(path);
    TextWriter tw = new StreamWriter(path);
    tw.WriteLine("The very first line!");
    tw.Close();
}
else if (File.Exists(path))
{
    TextWriter tw = new StreamWriter(path);
    tw.WriteLine("The next line!");
    tw.Close(); 
}

Pero la primera línea parece sobrescribirse siempre ... ¿cómo puedo evitar escribir en la misma línea (estoy usando esto en un bucle)?

Sé que es algo bastante simple, pero nunca he usado el WriteLinemétodo antes. Soy totalmente nuevo en C #.

Berker Yüceer
fuente
3
Tenga en cuenta que casi todas las respuestas aquí son incorrectas y están sujetas a condiciones de carrera . Recuerde: ¡el patrón if (file exists) { open file }casi siempre es incorrecto en todos los lenguajes de programación! Para .NET la solución es usar File.Open(path, FileMode.Append, FileAccess.ReadWrite)con las banderas apropiadas.
ComFreek
"Un valor de FileMode que especifica si se crea un archivo si no existe y determina si el contenido de los archivos existentes se retiene o se sobrescribe". lo mismo hecho por .net en lugar del enfoque manual aquí. Entonces, no está mal aquí, es el mismo proceso hecho manualmente. Puedes decir ineficiente pero decir mal no cuenta.
Berker Yüceer
La diferencia es: File.Opendelega internamente en una función WinAPI (ver el siguiente comentario) con la esperanza de prevenir la condición de carrera. La mayoría de las soluciones aquí no hacen esto y obviamente están sujetas a condiciones de carrera.
ComFreek
1
Sin embargo, la verificación de existencia está determinada por FileMode. Añada aquí ... y se dirige a una verificación de existencia y luego crea un archivo con CreateFileA. Todavía digo mal un poco extremo, pero puedes decir ineficiente. Tampoco debemos olvidar que la verificación de existencia no se puede usar solo para el acceso de escritura / lectura, sino también para otros asuntos, por lo que para los principiantes este tema es útil para comprender cómo funciona. Sin embargo, si puede agregar una respuesta que incluya todas las definiciones que escribió aquí y la razón por la cual es mejor, eso ayudaría mucho como respuesta y probablemente será elegido como correcto.
Berker Yüceer
1
@ComFreek Estoy totalmente de acuerdo en que debe escribir una respuesta completa al respecto para explicarlo claramente. Los comentarios no son para responder, y tengo una sincera curiosidad acerca de estas condiciones de carrera y cómo propones resolverlo.
Matthieu Foltzer

Respuestas:

167

Usa el constructor correcto :

else if (File.Exists(path))
{
    using(var tw = new StreamWriter(path, true))
    {
        tw.WriteLine("The next line!");
    }
}
Daniel Hilgarth
fuente
11
Primera respuesta, la respuesta más simple, la respuesta más útil para mí jajaja. Cuando lo miré pensé: ¿eh? basta con agregar ", verdadero"? ¿Cómo es que no lo veré antes? Maldición ... me sentí como un tonto gracias. Realmente prefiero estas buenas respuestas.
Berker Yüceer
77
pista: si el archivo no existe, este constructor crea un nuevo archivo.
Abou-Emish
1
envuelva i en un uso (vea la respuesta a continuación).
David Thielen
1
Cerrar es redundante, si lo has usado
Michael Freidgeim
2
-1 ¡Esto está sujeto a las condiciones de carrera y puede producir un comportamiento incorrecto! Quizás prefiera usar File.Open(path, FileMode.Append, FileAccess.ReadWrite)y verificar el tamaño del archivo a través de esa secuencia devuelta.
ComFreek
57
string path = @"E:\AppServ\Example.txt";
File.AppendAllLines(path, new [] { "The very first line!" });

Vea también File.AppendAllText (). AppendAllLines agregará una nueva línea a cada línea sin tener que colocarla usted mismo.

Ambos métodos crearán el archivo si no existe para que no tenga que hacerlo.

drch
fuente
3
Creo que esto es más apropiado para lo que el usuario preguntaba. Parece que hay 2 problemas. 1 es el texto que se sobrescribe; esto se debe a que WriteLine está sobrescribiendo el archivo. En este caso, File.AppendAllText es más apropiado. y 2) - la pregunta de cómo puedo crear mi archivo y saber que lo estoy agregando. Es bueno saberlo File.AppendAllText crea el archivo, esa fue mi pregunta. StreamWriter no siempre es apropiado, depende de para qué se use esa aplicación. En cualquier caso, esto me ayudó. +1
Devin C
42
string path=@"E:\AppServ\Example.txt";

if(!File.Exists(path))
{
   File.Create(path).Dispose();

   using( TextWriter tw = new StreamWriter(path))
   {
      tw.WriteLine("The very first line!");
   }

}    
else if (File.Exists(path))
{
   using(TextWriter tw = new StreamWriter(path))
   {
      tw.WriteLine("The next line!");
   }
}
Aek
fuente
También tengo el mismo problema, y ​​encuentro este póster, pero las soluciones aquí no resuelven mi problema. Así que uso algunas soluciones y solo agrego Dispose (). Mi objetivo no implica copiar y pegar.
Aek
1
No estoy sugiriendo que sí; Estoy diciendo que sin incluir eso en su respuesta, el póster original no sabrá por qué realizó los cambios que realizó o qué se supone que deben lograr. Siempre incluya toda la información relevante cuando publique, para que las personas sepan todo lo que está haciendo. :)
DiMono
1
Esto funciona porque no da un error que dice que no puede escribir en el archivo recién creado porque está siendo utilizado por otro proceso. El .Dispose () es la clave. Muchas gracias!
GenXisT
Esto de ninguna manera aborda la pregunta, que se trata de preservar los contenidos existentes.
Ben Voigt
No tiene sentido llamar Close()desde una usingdeclaración, ya que todos los recursos se cerrarán antes de ser eliminados automáticamente.
Sheridan
21

En realidad, no tiene que verificar si el archivo existe, ya que StreamWriter lo hará por usted. Si lo abre en modo append, el archivo se creará si no existe, siempre se agregará y nunca se sobrescribirá. Entonces su verificación inicial es redundante.

TextWriter tw = new StreamWriter(path, true);
tw.WriteLine("The next line!");
tw.Close(); 
John Boling
fuente
1
Estaba tratando de resolver la lógica de la respuesta aceptada, sabía que había hecho esto en una línea antes, pero no podía recordar la sintaxis exacta. Gracias.
Morvael
14

File.AppendAllText agrega una cadena a un archivo. También crea un archivo de texto si el archivo no existe. Si no necesita leer contenido, es muy eficiente. El caso de uso está registrando.

File.AppendAllText("C:\\log.txt", "hello world\n");
R.Cha
fuente
Esto es justo lo que necesitaba, pero ¿cómo puedo hacer que el nuevo contenido comience en una nueva línea? Estoy usando archivos CSV.
NiallUK
Supongo que no hay una solución simple. Te sugiero que revises esta publicación. stackoverflow.com/questions/1343044/…
R.Cha
3

Cuando inicia StreamWriter, se anula el texto que estaba allí antes. Puede usar la propiedad append de esta manera:

TextWriter t = new StreamWriter(path, true);
Matan Shahar
fuente
3
 else if (File.Exists(path)) 
{ 
  using (StreamWriter w = File.AppendText(path))
        {
            w.WriteLine("The next line!"); 
            w.Close();
        }
 } 
Tortazo
fuente
1
Si tiene el bloque 'usar', w.Close es redundante. Desechar al final de usar el bloque hace lo mismo.
Michael Freidgeim
-1 ¡Esto está sujeto a las condiciones de carrera y puede producir un comportamiento incorrecto! Quizás prefiera usar File.Open(path, FileMode.Append, FileAccess.ReadWrite)y verificar el tamaño del archivo a través de esa secuencia devuelta.
ComFreek
2

Prueba esto.

string path = @"E:\AppServ\Example.txt";
if (!File.Exists(path))
{
    using (var txtFile = File.AppendText(path))
    {
        txtFile.WriteLine("The very first line!");
    }
}
else if (File.Exists(path))
{     
    using (var txtFile = File.AppendText(path))
    {
        txtFile.WriteLine("The next line!");
    }
}
Asiri Jayaweera
fuente
Redudante File.AppendText(path), y con él no hay necesidad de verificar File.Exists(path). Y If (not A) Else If (A)es un extraño If / Else. Básicamente no hay nada bueno en esta pregunta, no hay código de explicación que sea una versión reductora de otra respuesta.
xdtTransform
-1 ¡Esto está sujeto a las condiciones de carrera y puede producir un comportamiento incorrecto! Quizás prefiera usar File.Open(path, FileMode.Append, FileAccess.ReadWrite)y verificar el tamaño del archivo a través de esa secuencia devuelta.
ComFreek
2

Puede usar el método File.AppendAllText () para resolver su problema. Este método se encargará de la creación de archivos si no está disponible, abriendo y cerrando el archivo.

var outputPath = @"E:\Example.txt";
var data = "Example Data";
File.AppendAllText(outputPath, data);
Vijay Shaaruck
fuente
1

A partir de la documentación de microsoft, puede crear un archivo si no existe y agregarlo en una sola llamada File.AppendAllText Method (String, String)

.NET Framework (versión actual) Otras versiones

Abre un archivo, agrega la cadena especificada al archivo y luego cierra el archivo. Si el archivo no existe, este método crea un archivo, escribe la cadena especificada en el archivo y luego lo cierra. Espacio de nombres: System.IO Assembly: mscorlib (en mscorlib.dll)

Sintaxis C # C ++ F # VB public static void AppendAllText (ruta de cadena, contenido de cadena) Ruta de parámetros Tipo: System.String El archivo al que se agrega la cadena especificada. contenido Tipo: System.String La cadena que se agregará al archivo.

AppendAllText

David Fawzy
fuente
1
using(var tw = new StreamWriter(path, File.Exists(path)))
{
    tw.WriteLine(message);
}
Andreas Gusakov
fuente
En general, las respuestas son mucho más útiles si incluyen una explicación de lo que se pretende que haga el código y por qué eso resuelve el problema sin introducir otros.
Tim Diekmann