BufferedWriter no escribe todo en su archivo de salida


Tengo un programa Java que lee texto de un archivo, línea por línea, y escribe texto nuevo en un archivo de salida. Pero no todo el texto que escribo en mi BufferedWriter aparece en el archivo de salida después de que el programa haya terminado. ¿Por qué es eso?

Los detalles: el programa toma un documento de texto CSV y lo convierte en comandos SQL para insertar los datos en una tabla. El archivo de texto tiene más de 10000 líneas que se ven similares a las siguientes:

2007,10,9,1,1,1006134,19423882

El programa parece funcionar bien excepto que solo se detiene en el archivo aleatoriamente a la mitad de la creación de una nueva instrucción SQL después de imprimirla en el archivo SQL. Se ve algo así como:

insert into nyccrash values (2007, 1, 2, 1, 4, 1033092, 259916);
insert into nyccrash values (2007, 1, 1, 1, 1, 1020246, 197687);
insert into nyccrash values (2007, 10, 9, 1

Esto sucede después de aproximadamente 10000 líneas, pero varios cientos de líneas antes del final del archivo. Donde ocurre la ruptura es entre a 1 y a ,. Sin embargo, los caracteres no parecen importantes porque si cambio el 1 a un 42 la última cosa escrita en el nuevo archivo es 4, que está cortando el 2 de ese entero. Así parece al igual que el lector o escritor debe estar muriendo después de escribir / leer una cierta cantidad.

Mi código Java es el siguiente:

import java.io.*;

public class InsertCrashData
{
    public static void main (String args[])
    {
        try
        {   
            //Open the input file.
            FileReader istream = new FileReader("nyccrash.txt");
            BufferedReader in = new BufferedReader(istream);
            //Open the output file.
            FileWriter ostream = new FileWriter("nyccrash.sql");
            BufferedWriter out = new BufferedWriter(ostream);
            String line, sqlstr;

            sqlstr = "CREATE TABLE nyccrash (crash_year integer, accident_type integer, collision_type integer, weather_condition integer, light_condition integer, x_coordinate integer, y_coordinate integer);\n\n"; 
            out.write(sqlstr);

            while((line = in.readLine())!= null)
            {
                String[] esa = line.split(",");
                sqlstr = "insert into nyccrash values ("+esa[0]+", "+esa[1]+", "+esa[2]+", "+esa[3]+", "+esa[4]+", "+esa[5]+", "+esa[6]+");\n";
                out.write(sqlstr);
            }
        }
        catch(Exception e)
        {
            System.out.println(e);
        }
    }
}
Author: Raedwald, 2012-11-17

8 answers

Necesita cerrar su OutputStream que eliminará el resto de sus datos:

out.close();

El tamaño predeterminado del búfer para BufferedWriter es 8192 caracteres, lo suficientemente grande como para contener fácilmente cientos de líneas de datos no escritos.

 59
Author: Reimeus,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-11-17 00:21:45

Que debe close() su BufferedWriter. Usted debe close() su BufferedWriter porque ES-Un Writer y así implementa AutoCloseable, lo que significa (énfasis añadido) es

Un recurso que debe cerrarse cuando ya no es necesario.

Algunas personas dicen que primero debes llamar flush() para su BufferedWriter antes de llamar close(). Están equivocados. La documentación de BufferedWriter.close() señala que " Cierra la secuencia, la descarga first " (sin cursiva en el original).

La semántica documentada del lavado (flush()) son

Limpia esta secuencia escribiendo cualquier salida en búfer en la secuencia subyacente

Por lo tanto, debe close, y close descargará cualquier salida de búfer.

Su archivo de salida no incluye todo el texto que escribió en su BufferedWriter porque almacenó parte de ese texto en un búfer. El BufferedWriter nunca vació ese búfer, pasándolo al archivo, porque nunca le dijiste que lo hiciera.


Desde Java 7, la mejor manera de garantizar que un recurso AutoCloseable, como un BufferedWriter, esté cerrado cuando ya no es necesario, es usar la administración automática de recursos (ARM), también conocida como try-with-resources :

 try (BufferedWriter out = new BufferedWriter(new FileWriter(file))) {
    // writes to out here
 } catch (IOException ex) {
    // handle ex
 }

También debe close su BufferedReader cuando ya no es necesario, por lo que debe tener anidados bloques de prueba con recursos:

 try (BufferedReader in = new BufferedReader(new FileReader("nyccrash.txt")) {
    try (BufferedWriter out = new BufferedWriter(new FileWriter("nyccrash.sql"))) {
       // your reading and writing code here
    }
 } catch (IOException ex) {
    // handle ex
 }
 9
Author: Raedwald,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 12:26:05

Un recurso que debe cerrarse cuando ya no se necesita.

finally {
    out.close();//this would resolve the issue
    }

Algunas cosas a considerar:

  • BufferedWriter.close() vacía el búfer a la secuencia subyacente, por lo que si olvida flush() y no cierra, es posible que su archivo no tenga todo el texto que escribió en él.
  • BufferedWriter.close() también cierra el Writer envuelto. Cuando se trata de un FileWriter, finalmente cerrará un FileOutputStream y le dirá al sistema operativo que ha terminado de escribir en el archivo.
  • El recolector de basura para llamar automáticamente a close(), no en el BufferedWriter o envuelto, FileWriter, pero en el FileOuputStream. Así que el sistema operativo estará feliz, pero hay que esperar a que el GC.
  • Sin embargo, siempre desea liberar recursos del sistema operativo tan pronto como ya no los necesite. Esto va para archivos abiertos, conexiones de base de datos, colas de impresión ... nada. Confía en mí en esto.
  • BufferedWriter.close() aclara el búfer de caracteres interno, de modo que la memoria estar disponible para la recolección de basura, incluso mientras el propio BufferedWriter permanece en el alcance.

Por lo tanto, siempre cierre sus recursos (no solo archivos) cuando haya terminado con ellos.

Si realmente quieres echar un vistazo debajo de las portadas, la mayor parte del código fuente de la API de Java está disponible. BufferedWriter está aquí.

 6
Author: Jaimin Patel,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-02-14 14:58:22

Su código no parece estar cerrando el escritor después de que haya terminado de escribir en él. Agregue un out.close() (preferiblemente en un bloque finally) y debería funcionar correctamente.

 5
Author: Ian Roberts,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-11-16 23:58:47

No cierras tu BufferedWriter.cerrar dentro de un bloque final

   finally {
    out.close();//this would resolve the issue
    }
 5
Author: PermGenError,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-11-16 23:58:56

No cierras tu BufferedWriter.cerrar dentro de un bloque final

finally {
out.close();//this would resolve the issue
}

Esto funciona. Me he enfrentado al mismo problema y esto funcionó para mí..Buena Suerte :)

 1
Author: Harini,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-04-02 14:08:16

Siempre cierre sus recursos (no solo archivos) cuando haya terminado con ellos.

 finally {
    out.close();//this would resolve the issue
    }

Puede haber situaciones en las que desee vaciar el búfer sin cerrar el archivo. En estas situaciones puede utilizar el método flush.

 1
Author: Harita M,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-08-11 11:36:36

Ya que estás usando BufferedWriter también puedes vaciar el búfer cuando sea apropiado:

out.flush()

Esto escribirá el resto del búfer en el archivo real. Close-method también limpia el búfer y cierra el archivo.

out.close()

Puede haber situaciones en las que desee vaciar el búfer sin cerrar el archivo. En estas situaciones puede utilizar el método flush.

También puede usar el método newline de BuffredWriter en lugar de agregar \n al final de la línea. Método de nueva línea utiliza un separador de línea específico del sistema para que su código funcione en diferentes plataformas.

out.newLine()
 0
Author: niklasgerdt,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-11-24 15:15:53