.NET File.WriteAllLines deja una línea vacía al final del archivo

Cuando estoy guardando el contenido de la matriz String[] con System.IO.File.WriteAllLines, al final de un archivo siempre se deja una línea en blanco. Por ejemplo:

System.IO.File.WriteAllLines(Application.dataPath + "/test.txt",["a", "b", "c"]);

Produce archivo (sin guion bajo):

a
b
c
_

Ya había tal tema: Línea vacía en .Net File.WriteAllLines, ¿es un error? , pero el autor dijo que "Creo que hay algún problema con mis datos, ese es mi problema, pero no WritAllLines" y se cerró como "demasiado localizado" (?!?).

¿Es un error? ¿Cómo puedo deshacerme fácilmente de él (por ahora solo lo ignoro cuando vuelvo a leer el archivo)?

preguntado el 27 de julio de 12 a las 15:07

¿La última entrada en la matriz termina con una nueva línea? -

He mostrado una matriz ejemplar dada como argumento: ["a", "b", "c"] Contiene solo letras habituales. -

9 Respuestas

También puede guardar un archivo con WriteAllText y unir una matriz de líneas manualmente como:

File.WriteAllText(file, String.Join("\r\n",correctedLines));

Respondido el 25 de Septiembre de 19 a las 08:09

Hay una solución más simple:

// 1. Convert the items on the array to single string with the separator "\n" between the items
string AllItemsInOneString= string.Join("\n", StringArrayToSave);

// 2. Save with WriteAllText instead
File.WriteAllText(FilePath, AllItemsInOneString);

Respondido 13 ago 19, 19:08

Los programas WriteAllLines El método escribirá cada línea en su matriz seguida de un salto de línea. Esto significa que siempre obtendrá esta "línea vacía" en su archivo.

El punto hecho en la publicación que vinculó es que cuando se ejecuta ReadAllLines que considera una línea como caracteres terminados por un salto de línea. Entonces, cuando usa el método de lectura en el archivo que acaba de escribir, debería obtener exactamente las mismas líneas.

Si está leyendo el archivo de una manera diferente, tendrá que lidiar con los saltos de línea usted mismo.

Esencialmente, lo que está viendo es el comportamiento esperado.

Respondido 27 Jul 12, 15:07

Entiendo que la mejor manera de deshacerse de él será simplemente usando WriteAllText con String.Join con \r\n como separador? - user1557862

Mira también esta pregunta sobre las actuaciones de String.Join y StringBuilder - Steve

Dado que siempre hay una "última línea", esté vacía o no, no entiendo por qué la última línea escrita debe estar vacía. El último elemento de la matriz que resulta de ReadAllLines es una línea de archivo que no termina con un salto de línea, es solo la última línea. Compare los archivos guardados por WriteAllLines con los archivos guardados por XmlSerializer.Serialize y verá lo que quiero decir. - Tiago Freitas Leal

@TiagoFreitasLeal: Todo tiene que ver con lo que dije en mi primer párrafo. La forma en que funciona el código es escribir cada elemento de su matriz seguido de un salto de línea. Esto significa que el último elemento de su matriz irá seguido de un salto de línea. Esto significa que el archivo termina en un salto de línea, lo que significa que hay una cadena vacía en esa última línea. Este es un producto necesario de cualquier representación de esa nueva línea final (si no está seguro de por qué, considere cómo representaría la diferencia entre el mismo archivo con y sin esa nueva línea final). - Chris

También en respuesta a "El último elemento de matriz que resulta de ReadAllLines es una línea de archivo que no termina con un salto de línea", esto no es cierto. Puede esperar que el comportamiento sea que coloque una nueva línea entre cada elemento, lo que daría como resultado que no haya una nueva línea al final del archivo. Sin embargo, no es así como funciona. Internamente hace más o menos un foreach a través de la entrada y para cada elemento hace un WriteLine. WriteLine Es por eso que cada elemento termina con una nueva línea. Independientemente de lo que crea que es la forma correcta de hacer esto, por supuesto que no es importante, así es como funciona el código. - Chris

Como otros han señalado, así es como funciona. Aquí hay un método que lo hace sin la nueva línea adicional:

public static class FileExt
{
    public static void WriteAllLinesBetter(string path, params string[] lines)
    {
        if (path == null)
            throw new ArgumentNullException("path");
        if (lines == null)
            throw new ArgumentNullException("lines");

        using (var stream = File.OpenWrite(path))
        using (StreamWriter writer = new StreamWriter(stream))
        {
            if (lines.Length > 0)
            {
                for (int i = 0; i < lines.Length - 1; i++)
                {
                    writer.WriteLine(lines[i]);
                }
                writer.Write(lines[lines.Length - 1]);
            }
        }
    }
}

Uso:

FileExt.WriteAllLinesBetter("test.txt", "a", "b", "c");

Escribe:

aentrar
bentrar
c

Respondido el 25 de enero de 19 a las 09:01

Funciona de maravilla. - Tiago Freitas Leal

La solución @Virtlink es casi Perfecto. De hecho, hay un escenario en el que obtendrá basura al final del archivo, cuando el archivo existe y su contenido es más grande que el contenido nuevo. Antes de escribir el nuevo contenido del archivo, simplemente restablezca la longitud del archivo a cero.

    public static void WriteAllLinesBetter(string path, params string[] lines)
    {
        if (path == null)
            throw new ArgumentNullException("path");
        if (lines == null)
            throw new ArgumentNullException("lines");

        using (var stream = File.OpenWrite(path))
        {
            stream.SetLength(0);
            using (var writer = new StreamWriter(stream))
            {
                if (lines.Length > 0)
                {
                    for (var i = 0; i < lines.Length - 1; i++)
                    {
                        writer.WriteLine(lines[i]);
                    }
                    writer.Write(lines[lines.Length - 1]);
                }
            }
        }
    }

Respondido 03 Feb 17, 22:02

Encontré esto también, buen lugar. Felicitaciones por cambiar a var writer. - Waescher

WriteAllLines escribe cada entrada en su matriz y agrega una nueva línea.
Como puede ver, cada cadena está en su propia línea, esto significa que su última entrada está terminada en una nueva línea y ve una línea más en el archivo. Podría probar esto con un volcado hexadecimal del archivo

Mirar el código fuente de WriteAllLines lo confirma.
Internamente, utiliza el TextWriter.WriteLine(cadena) método.

Respondido 27 Jul 12, 15:07

hice lo mismo solo agregando una línea: 3, espero que ayude a alguien

    for(int i = 0; i < Length; i++)
    {
        line = getLocation(i).X.ToString("0.0", nfi) + ',' + getLocation(i).Y.ToString("0.000", nfi) + ',' + getColorRaw(i).R.ToString("0.000", nfi) + ',' + getColorRaw(i).G.ToString("0.000", nfi) + ',' + getColorRaw(i).B.ToString("0.000", nfi);
        writer.Write(line);
        if( i < Length - 1) writer.Write("\n");

Respondido 20 Abr '13, 04:04

Para deshacerse de la nueva línea final, la mejor solución sería, cuando lo lea con .ReadAllLines() para descartar realmente el último elemento de su matriz de cadenas.

Respondido el 14 de junio de 14 a las 00:06

Esa sería una solución parcial en caso de que se lea una cadena vacía en la estructura de matriz receptora. La pregunta hace parecer que este no es el caso. - Félix Frank

La forma más fácil de hacerlo fue usar AppendAllText para la última línea:

if ($i -ne $lines.Count - 1){
     $newLines += $lines[$i]
    } else {
     $lastLine = $lines[$i]
}

[IO.File]::WriteAllLines($file.FullName, $newLines);
[IO.File]::AppendAllText($file.FullName, $lastLine);

Respondido el 13 de Septiembre de 16 a las 11:09

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.