txt texto separado segunda por modificar linea leer grandes ejemplos como comas archivos archivo java performance file-io bufferedreader

segunda - leer un archivo de texto separado por comas en java



La forma más rápida de leer y escribir archivos grandes línea por línea en Java (4)

He estado buscando mucho la forma más rápida de leer y escribir nuevamente archivos grandes (0.5 - 1 GB) en Java con memoria limitada (aproximadamente 64MB). Cada línea del archivo representa un registro, por lo que debo obtenerlos línea por línea. El archivo es un archivo de texto normal.

Intenté BufferedReader y BufferedWriter, pero no parece ser la mejor opción. Toma aproximadamente 35 segundos leer y escribir un archivo de tamaño de 0,5 GB, solo lectura de escritura sin procesamiento. Creo que el cuello de botella aquí está escribiendo, ya que leer solo lleva unos 10 segundos.

Traté de leer una matriz de bytes, pero luego buscar líneas en cada matriz que fue leída lleva más tiempo.

Alguna sugerencia por favor? Gracias


Lo primero que intentaré es aumentar el tamaño del buffer de BufferedReader y BufferedWriter. Los tamaños de búfer predeterminados no están documentados, pero al menos en Oracle VM son 8192 caracteres, lo que no brindará mucha ventaja de rendimiento.

Si solo necesita hacer una copia del archivo (y no necesita acceso real a los datos), soltaría el enfoque Reader / Writer y trabajaría directamente con InputStream y OutputStream usando una matriz de bytes como buffer:

FileInputStream fis = new FileInputStream("d:/test.txt"); FileOutputStream fos = new FileOutputStream("d:/test2.txt"); byte[] b = new byte[bufferSize]; int r; while ((r=fis.read(b))>=0) { fos.write(b, 0, r); } fis.close(); fos.close();

o realmente usa NIO:

FileChannel in = new RandomAccessFile("d:/test.txt", "r").getChannel(); FileChannel out = new RandomAccessFile("d:/test2.txt", "rw").getChannel(); out.transferFrom(in, 0, Long.MAX_VALUE); in.close(); out.close();

Sin embargo, cuando se comparan los diferentes métodos de copia, tengo diferencias mucho más grandes (duración) entre cada ejecución del índice de referencia que entre las diferentes implementaciones. El almacenamiento en memoria caché de E / S (tanto en el nivel del sistema operativo como en la memoria caché del disco duro) juega un gran papel aquí y es muy difícil decir qué es más rápido. En mi hardware, copiar un archivo de texto de 1GB línea por línea utilizando BufferedReader y BufferedWriter lleva menos de 5 segundos en algunas ejecuciones y más de 30 en otras.


Sospecho que su verdadero problema es que tiene hardware limitado y lo que hace es software no hará mucha diferencia. Si tiene mucha memoria y CPU, los trucos más avanzados pueden ayudar, pero si solo está esperando en su disco duro porque el archivo no está en la memoria caché, no hará mucha diferencia.

Por cierto: 500 MB en 10 segundos o 50 MB / s es una velocidad de lectura típica para un HDD.

Intente ejecutar lo siguiente para ver en qué punto su sistema no puede almacenar en caché el archivo de manera eficiente.

public static void main(String... args) throws IOException { for (int mb : new int[]{50, 100, 250, 500, 1000, 2000}) testFileSize(mb); } private static void testFileSize(int mb) throws IOException { File file = File.createTempFile("test", ".txt"); file.deleteOnExit(); char[] chars = new char[1024]; Arrays.fill(chars, ''A''); String longLine = new String(chars); long start1 = System.nanoTime(); PrintWriter pw = new PrintWriter(new FileWriter(file)); for (int i = 0; i < mb * 1024; i++) pw.println(longLine); pw.close(); long time1 = System.nanoTime() - start1; System.out.printf("Took %.3f seconds to write to a %d MB, file rate: %.1f MB/s%n", time1 / 1e9, file.length() >> 20, file.length() * 1000.0 / time1); long start2 = System.nanoTime(); BufferedReader br = new BufferedReader(new FileReader(file)); for (String line; (line = br.readLine()) != null; ) { } br.close(); long time2 = System.nanoTime() - start2; System.out.printf("Took %.3f seconds to read to a %d MB file, rate: %.1f MB/s%n", time2 / 1e9, file.length() >> 20, file.length() * 1000.0 / time2); file.delete(); }

En una máquina Linux con mucha memoria.

Took 0.395 seconds to write to a 50 MB, file rate: 133.0 MB/s Took 0.375 seconds to read to a 50 MB file, rate: 140.0 MB/s Took 0.669 seconds to write to a 100 MB, file rate: 156.9 MB/s Took 0.569 seconds to read to a 100 MB file, rate: 184.6 MB/s Took 1.585 seconds to write to a 250 MB, file rate: 165.5 MB/s Took 1.274 seconds to read to a 250 MB file, rate: 206.0 MB/s Took 2.513 seconds to write to a 500 MB, file rate: 208.8 MB/s Took 2.332 seconds to read to a 500 MB file, rate: 225.1 MB/s Took 5.094 seconds to write to a 1000 MB, file rate: 206.0 MB/s Took 5.041 seconds to read to a 1000 MB file, rate: 208.2 MB/s Took 11.509 seconds to write to a 2001 MB, file rate: 182.4 MB/s Took 9.681 seconds to read to a 2001 MB file, rate: 216.8 MB/s

En una máquina de Windows con mucha memoria.

Took 0.376 seconds to write to a 50 MB, file rate: 139.7 MB/s Took 0.401 seconds to read to a 50 MB file, rate: 131.1 MB/s Took 0.517 seconds to write to a 100 MB, file rate: 203.1 MB/s Took 0.520 seconds to read to a 100 MB file, rate: 201.9 MB/s Took 1.344 seconds to write to a 250 MB, file rate: 195.4 MB/s Took 1.387 seconds to read to a 250 MB file, rate: 189.4 MB/s Took 2.368 seconds to write to a 500 MB, file rate: 221.8 MB/s Took 2.454 seconds to read to a 500 MB file, rate: 214.1 MB/s Took 4.985 seconds to write to a 1001 MB, file rate: 210.7 MB/s Took 5.132 seconds to read to a 1001 MB file, rate: 204.7 MB/s Took 10.276 seconds to write to a 2003 MB, file rate: 204.5 MB/s Took 9.964 seconds to read to a 2003 MB file, rate: 210.9 MB/s



En Java 7 puede usar los métodos Files.readAllLines () y Files.write (). Aquí está el ejemplo:

List<String> readTextFile(String fileName) throws IOException { Path path = Paths.get(fileName); return Files.readAllLines(path, StandardCharsets.UTF_8); } void writeTextFile(List<String> strLines, String fileName) throws IOException { Path path = Paths.get(fileName); Files.write(path, strLines, StandardCharsets.UTF_8); }