txt texto por manejo linea leer grandes ejemplos ejemplo como archivos archivo java performance file types io

manejo - leer un archivo de texto en java linea por linea



¿Cuál es la forma más rápida de leer una gran cantidad de archivos pequeños en la memoria? (6)

Cualquier enfoque convencional va a ser limitado en velocidad. No estoy seguro de que veas una gran diferencia entre un enfoque y otro.

Me concentraría en trucos de negocios que podrían acelerar toda la operación.

Por ejemplo, si leyó todos los archivos y los almacenó en un solo archivo con las marcas de tiempo de cada uno de sus archivos originales, entonces podría verificar si alguno de los archivos ha cambiado sin abrirlos realmente. (un simple caché, en otras palabras).

Si su problema fue obtener una GUI rápidamente, es posible que encuentre una manera de abrir los archivos en una secuencia de fondo después de que se muestre su primera pantalla.

El sistema operativo puede ser bastante bueno con los archivos, si esto es parte de un proceso por lotes (sin E / S de usuario), podría comenzar con un archivo por lotes que agregue todos los archivos en uno grande antes de iniciar java, usando algo como esto:

echo "file1" > file.all type "file1" >> file.all echo "file2" >> file.all type "file2" >> file.all

Luego simplemente abre file.all (no estoy seguro de qué tan rápido será, pero probablemente sea el enfoque más rápido para las condiciones que acabo de indicar)

Supongo que solo digo que la mayoría de las veces, una solución a un problema de velocidad a menudo requiere ampliar un poco su punto de vista y repensar completamente la solución utilizando nuevos parámetros. Las modificaciones de un algoritmo existente usualmente solo dan mejoras menores de velocidad a costa de la legibilidad.

Necesito leer ~ 50 archivos en cada inicio de servidor y colocar cada representación de archivo de texto en la memoria. Cada archivo de texto tendrá su propia cadena (¿cuál es el mejor tipo para usar para el titular de la cadena?).

¿Cuál es la forma más rápida de leer los archivos en la memoria y cuál es la mejor estructura / tipo de datos para guardar el texto para poder manipularlo en la memoria (buscar y reemplazar principalmente)?

Gracias



Depende mucho de la estructura interna de sus archivos de texto y de lo que pretende hacer con ellos.

¿Son los archivos los diccionarios de valor-clave (es decir, los archivos de "propiedades")? XML? JSON? Tienes estructuras estándar para esos.

Si tienen una estructura formal, también puede usar JavaCC para construir una representación de objetos de los archivos.

De lo contrario, si son solo manchas de datos, bueno, lea los archivos y colóquelos en una cadena.

Edición: acerca de buscar y reemplazar, use la función replaceAll de String .


Después de buscar en google las pruebas existentes de velocidad de E / S en Java, debo decir que el caso de prueba de TofuBear me abrió los ojos por completo. Tienes que ejecutar su prueba en tu propia plataforma para ver qué es lo más rápido para ti.

Después de ejecutar su prueba y agregar algunas de las mías (Crédito a TofuBear por publicar su código original), parece que puede obtener aún más velocidad al usar su propio búfer personalizado en lugar de usar BufferedInputStream.

Para mi consternación, el ByteBuffer de NIO no funcionó bien.

NOTA: El byte estático [] del búfer se redujo unos pocos ms, ¡pero los ByteBuffers estáticos aumentaron el tiempo para procesar! ¿Hay algún problema con el código?

He añadido algunas pruebas:

  1. ArrayTest_CustomBuffering (Leer datos directamente en mi propio búfer)

  2. ArrayTest_CustomBuffering_StaticBuffer (Lee datos en un búfer estático que se crea solo una vez al principio)

  3. FileChannelArrayByteBuffer (use ByteBuffer de NIO y ajuste su propio byte [] array)

  4. FileChannelAllocateByteBuffer (use ByteBuffer NIO con .allocate)

  5. FileChannelAllocateByteBuffer_StaticBuffer (igual que 4 pero con un buffer estático)

  6. FileChannelAllocateDirectByteBuffer (use ByteBuffer de NIO con .allocateDirect)

  7. FileChannelAllocateDirectByteBuffer_StaticBuffer (igual que 6 pero con un buffer estático)

Aquí están mis resultados: usando Windows Vista y jdk1.6.0_13 en el rt.jar extraído: ArrayTest
tiempo = 2075
bytes = 2120336424
Prueba de Array
tiempo = 2044
bytes = 2120336424
ArrayTest_CustomBuffering
tiempo = 1903
bytes = 2120336424
ArrayTest_CustomBuffering_StaticBuffer
tiempo = 1872
bytes = 2120336424
DataInputByteAtATime
tiempo = 2668
bytes = 2120336424
DataInputReadFully
tiempo = 2028
bytes = 2120336424
MemoryMapped
tiempo = 2901
bytes = 2120336424
FileChannelArrayByteBuffer
tiempo = 2371
bytes = 2120336424
FileChannelAllocateByteBuffer
tiempo = 2356
bytes = 2120336424
FileChannelAllocateByteBuffer_StaticBuffer
tiempo = 2668
bytes = 2120336424
FileChannelAllocateDirectByteBuffer
tiempo = 2512
bytes = 2120336424
FileChannelAllocateDirectByteBuffer_StaticBuffer
tiempo = 2590
bytes = 2120336424

Mi versión pirateada del código de TofuBear:

import java.io.BufferedInputStream; import java.io.DataInputStream; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.nio.MappedByteBuffer; import java.nio.ByteBuffer; import java.nio.channels.FileChannel; import java.nio.channels.FileChannel.MapMode; import java.util.HashSet; import java.util.Set; public class Main { public static void main(final String[] argv) { ArrayTest.mainx(argv); ArrayTest.mainx(argv); ArrayTest_CustomBuffering.mainx(argv); ArrayTest_CustomBuffering_StaticBuffer.mainx(argv); DataInputByteAtATime.mainx(argv); DataInputReadFully.mainx(argv); MemoryMapped.mainx(argv); FileChannelArrayByteBuffer.mainx(argv); FileChannelAllocateByteBuffer.mainx(argv); FileChannelAllocateByteBuffer_StaticBuffer.mainx(argv); FileChannelAllocateDirectByteBuffer.mainx(argv); FileChannelAllocateDirectByteBuffer_StaticBuffer.mainx(argv); } } abstract class Test { static final int BUFF_SIZE = 20971520; static final byte[] StaticData = new byte[BUFF_SIZE]; static final ByteBuffer StaticBuffer =ByteBuffer.allocate(BUFF_SIZE); static final ByteBuffer StaticDirectBuffer = ByteBuffer.allocateDirect(BUFF_SIZE); public final void run(final File root) { final Set<File> files; final long size; final long start; final long end; final long total; files = new HashSet<File>(); getFiles(root, files); start = System.currentTimeMillis(); size = readFiles(files); end = System.currentTimeMillis(); total = end - start; System.out.println(getClass().getName()); System.out.println("time = " + total); System.out.println("bytes = " + size); } private void getFiles(final File dir,final Set<File> files) { final File[] childeren; childeren = dir.listFiles(); for(final File child : childeren) { if(child.isFile()) { files.add(child); } else { getFiles(child, files); } } } private long readFiles(final Set<File> files) { long size; size = 0; for(final File file : files) { size += readFile(file); } return (size); } protected abstract long readFile(File file); } class ArrayTest extends Test { public static void mainx(final String[] argv) { final Test test; test = new ArrayTest(); test.run(new File(argv[0])); } protected long readFile(final File file) { InputStream stream; stream = null; try { final byte[] data; int soFar; int sum; stream = new BufferedInputStream(new FileInputStream(file)); data = new byte[(int)file.length()]; soFar = 0; do { soFar += stream.read(data, soFar, data.length - soFar); } while(soFar != data.length); sum = 0; for(final byte b : data) { sum += b; } return (sum); } catch(final IOException ex) { ex.printStackTrace(); } finally { if(stream != null) { try { stream.close(); } catch(final IOException ex) { ex.printStackTrace(); } } } return (0); } } class ArrayTest_CustomBuffering extends Test { public static void mainx(final String[] argv) { final Test test; test = new ArrayTest_CustomBuffering(); test.run(new File(argv[0])); } protected long readFile(final File file) { InputStream stream; stream = null; try { final byte[] data; int soFar; int sum; stream = new FileInputStream(file); data = new byte[(int)file.length()]; soFar = 0; do { soFar += stream.read(data, soFar, data.length - soFar); } while(soFar != data.length); sum = 0; for(final byte b : data) { sum += b; } return (sum); } catch(final IOException ex) { ex.printStackTrace(); } finally { if(stream != null) { try { stream.close(); } catch(final IOException ex) { ex.printStackTrace(); } } } return (0); } } class ArrayTest_CustomBuffering_StaticBuffer extends Test { public static void mainx(final String[] argv) { final Test test; test = new ArrayTest_CustomBuffering_StaticBuffer(); test.run(new File(argv[0])); } protected long readFile(final File file) { InputStream stream; stream = null; try { int soFar; int sum; final int fileSize; stream = new FileInputStream(file); fileSize = (int)file.length(); soFar = 0; do { soFar += stream.read(StaticData, soFar, fileSize - soFar); } while(soFar != fileSize); sum = 0; for(int i=0;i<fileSize;i++) { sum += StaticData[i]; } return (sum); } catch(final IOException ex) { ex.printStackTrace(); } finally { if(stream != null) { try { stream.close(); } catch(final IOException ex) { ex.printStackTrace(); } } } return (0); } } class DataInputByteAtATime extends Test { public static void mainx(final String[] argv) { final Test test; test = new DataInputByteAtATime(); test.run(new File(argv[0])); } protected long readFile(final File file) { DataInputStream stream; stream = null; try { final int fileSize; int sum; stream = new DataInputStream(new BufferedInputStream(new FileInputStream(file))); fileSize = (int)file.length(); sum = 0; for(int i = 0; i < fileSize; i++) { sum += stream.readByte(); } return (sum); } catch(final IOException ex) { ex.printStackTrace(); } finally { if(stream != null) { try { stream.close(); } catch(final IOException ex) { ex.printStackTrace(); } } } return (0); } } class DataInputReadFully extends Test { public static void mainx(final String[] argv) { final Test test; test = new DataInputReadFully(); test.run(new File(argv[0])); } protected long readFile(final File file) { DataInputStream stream; stream = null; try { final byte[] data; int sum; stream = new DataInputStream(new BufferedInputStream(new FileInputStream(file))); data = new byte[(int)file.length()]; stream.readFully(data); sum = 0; for(final byte b : data) { sum += b; } return (sum); } catch(final IOException ex) { ex.printStackTrace(); } finally { if(stream != null) { try { stream.close(); } catch(final IOException ex) { ex.printStackTrace(); } } } return (0); } } class DataInputReadInChunks extends Test { public static void mainx(final String[] argv) { final Test test; test = new DataInputReadInChunks(); test.run(new File(argv[0])); } protected long readFile(final File file) { DataInputStream stream; stream = null; try { final byte[] data; int size; final int fileSize; int sum; stream = new DataInputStream(new BufferedInputStream(new FileInputStream(file))); fileSize = (int)file.length(); data = new byte[512]; size = 0; sum = 0; do { size += stream.read(data); sum = 0; for(int i = 0; i < size; i++) { sum += data[i]; } } while(size != fileSize); return (sum); } catch(final IOException ex) { ex.printStackTrace(); } finally { if(stream != null) { try { stream.close(); } catch(final IOException ex) { ex.printStackTrace(); } } } return (0); } } class MemoryMapped extends Test { public static void mainx(final String[] argv) { final Test test; test = new MemoryMapped(); test.run(new File(argv[0])); } protected long readFile(final File file) { FileInputStream stream; stream = null; try { final FileChannel channel; final MappedByteBuffer buffer; final int fileSize; int sum; stream = new FileInputStream(file); channel = stream.getChannel(); buffer = channel.map(MapMode.READ_ONLY, 0, file.length()); fileSize = (int)file.length(); sum = 0; for(int i = 0; i < fileSize; i++) { sum += buffer.get(); } return (sum); } catch(final IOException ex) { ex.printStackTrace(); } finally { if(stream != null) { try { stream.close(); } catch(final IOException ex) { ex.printStackTrace(); } } } return (0); } } class FileChannelArrayByteBuffer extends Test { public static void mainx(final String[] argv) { final Test test; test = new FileChannelArrayByteBuffer(); test.run(new File(argv[0])); } protected long readFile(final File file) { FileInputStream stream; stream = null; try { final byte[] data; final FileChannel channel; final ByteBuffer buffer; int nRead=0; final int fileSize; int sum; stream = new FileInputStream(file); data = new byte[(int)file.length()]; buffer = ByteBuffer.wrap(data); channel = stream.getChannel(); fileSize = (int)file.length(); nRead += channel.read(buffer); buffer.rewind(); sum = 0; for(int i = 0; i < fileSize; i++) { sum += buffer.get(); } return (sum); } catch(final IOException ex) { ex.printStackTrace(); } finally { if(stream != null) { try { stream.close(); } catch(final IOException ex) { ex.printStackTrace(); } } } return (0); } } class FileChannelAllocateByteBuffer extends Test { public static void mainx(final String[] argv) { final Test test; test = new FileChannelAllocateByteBuffer(); test.run(new File(argv[0])); } protected long readFile(final File file) { FileInputStream stream; stream = null; try { final byte[] data; final FileChannel channel; final ByteBuffer buffer; int nRead=0; final int fileSize; int sum; stream = new FileInputStream(file); //data = new byte[(int)file.length()]; buffer = ByteBuffer.allocate((int)file.length()); channel = stream.getChannel(); fileSize = (int)file.length(); nRead += channel.read(buffer); buffer.rewind(); sum = 0; for(int i = 0; i < fileSize; i++) { sum += buffer.get(); } return (sum); } catch(final IOException ex) { ex.printStackTrace(); } finally { if(stream != null) { try { stream.close(); } catch(final IOException ex) { ex.printStackTrace(); } } } return (0); } } class FileChannelAllocateDirectByteBuffer extends Test { public static void mainx(final String[] argv) { final Test test; test = new FileChannelAllocateDirectByteBuffer(); test.run(new File(argv[0])); } protected long readFile(final File file) { FileInputStream stream; stream = null; try { final byte[] data; final FileChannel channel; final ByteBuffer buffer; int nRead=0; final int fileSize; int sum; stream = new FileInputStream(file); //data = new byte[(int)file.length()]; buffer = ByteBuffer.allocateDirect((int)file.length()); channel = stream.getChannel(); fileSize = (int)file.length(); nRead += channel.read(buffer); buffer.rewind(); sum = 0; for(int i = 0; i < fileSize; i++) { sum += buffer.get(); } return (sum); } catch(final IOException ex) { ex.printStackTrace(); } finally { if(stream != null) { try { stream.close(); } catch(final IOException ex) { ex.printStackTrace(); } } } return (0); } } class FileChannelAllocateByteBuffer_StaticBuffer extends Test { public static void mainx(final String[] argv) { final Test test; test = new FileChannelAllocateByteBuffer_StaticBuffer(); test.run(new File(argv[0])); } protected long readFile(final File file) { FileInputStream stream; stream = null; try { final byte[] data; final FileChannel channel; int nRead=0; final int fileSize; int sum; stream = new FileInputStream(file); //data = new byte[(int)file.length()]; StaticBuffer.clear(); StaticBuffer.limit((int)file.length()); channel = stream.getChannel(); fileSize = (int)file.length(); nRead += channel.read(StaticBuffer); StaticBuffer.rewind(); sum = 0; for(int i = 0; i < fileSize; i++) { sum += StaticBuffer.get(); } return (sum); } catch(final IOException ex) { ex.printStackTrace(); } finally { if(stream != null) { try { stream.close(); } catch(final IOException ex) { ex.printStackTrace(); } } } return (0); } } class FileChannelAllocateDirectByteBuffer_StaticBuffer extends Test { public static void mainx(final String[] argv) { final Test test; test = new FileChannelAllocateDirectByteBuffer_StaticBuffer(); test.run(new File(argv[0])); } protected long readFile(final File file) { FileInputStream stream; stream = null; try { final byte[] data; final FileChannel channel; int nRead=0; final int fileSize; int sum; stream = new FileInputStream(file); //data = new byte[(int)file.length()]; StaticDirectBuffer.clear(); StaticDirectBuffer.limit((int)file.length()); channel = stream.getChannel(); fileSize = (int)file.length(); nRead += channel.read(StaticDirectBuffer); StaticDirectBuffer.rewind(); sum = 0; for(int i = 0; i < fileSize; i++) { sum += StaticDirectBuffer.get(); } return (sum); } catch(final IOException ex) { ex.printStackTrace(); } finally { if(stream != null) { try { stream.close(); } catch(final IOException ex) { ex.printStackTrace(); } } } return (0); } }


La forma más eficiente es:

  • Determine la longitud del archivo ( File.length() )
  • Crea un búfer de caracteres con el mismo tamaño (o un poco más grande)
  • Determinar la codificación del archivo.
  • Use el new InputStreamReader (new FileInputStream(file), encoding) para leer
  • Lea el archivo while en el búfer con una sola llamada para leer (). Tenga en cuenta que read () puede volver pronto (no haber leído el archivo completo). En ese caso, llámelo nuevamente con un desplazamiento para leer el siguiente lote.
  • Crear la cadena: new String(buffer)

Si necesita buscar y reemplazar una vez al inicio, use String.replaceAll ().

Si necesita hacerlo repetidamente, puede considerar usar StringBuilder. No tiene replaceAll () pero puede usarlo para manipular la matriz de caracteres en su lugar (-> sin asignación de memoria).

Dicho esto:

  1. Haga su código lo más corto y simple posible.
  2. Medir el rendimiento
  3. Es muy lento, arréglalo.

No hay razón para perder mucho tiempo en hacer que este código se ejecute rápidamente si solo se necesitan 0.1s.

Si todavía tiene un problema de rendimiento, considere la posibilidad de colocar todos los archivos de texto en un JAR, agregarlo a la ruta de clase y usar Class.getResourceAsStream () para leer los archivos. Cargar cosas desde el classpath de Java está altamente optimizado.


Un archivo asignado en memoria será más rápido ... algo como esto:

final File file; final FileChannel channel; final MappedByteBuffer buffer; file = new File(fileName); fin = new FileInputStream(file); channel = fin.getChannel(); buffer = channel.map(MapMode.READ_ONLY, 0, file.length());

y luego proceder a leer desde el buffer de bytes.

Esto será significativamente más rápido que FileInputStream o FileReader .

EDITAR:

Después de un poco de investigación con esto, resulta que, dependiendo de su sistema operativo, podría estar mejor utilizando un nuevo BufferedInputStream(new FileInputStream(file)) lugar. Sin embargo, al leer todo el contenido de una vez en un char [], el tamaño del archivo parece ser el peor.

Por lo tanto, BufferedInputStream debería ofrecer un rendimiento más o menos constante en todas las plataformas, mientras que el archivo asignado en la memoria puede ser lento o rápido según el sistema operativo subyacente. Al igual que con todo lo que es crítico para el rendimiento, debe probar su código y ver qué funciona mejor.

EDITAR:

Bien, aquí hay algunas pruebas (la primera se realiza dos veces para obtener los archivos en la memoria caché del disco).

Lo ejecuté en los archivos de la clase rt.jar, extraídos al disco duro, esto es bajo Windows 7 beta x64. Eso es 16784 archivos con un total de 94,706,637 bytes.

Primero los resultados ...

(recuerde que lo primero se repite para obtener la configuración del caché de disco)

  • Prueba de Array

    • tiempo = 83016
    • bytes = 118641472
  • Prueba de Array

    • tiempo = 46570
    • bytes = 118641472
  • DataInputByteAtATime

    • tiempo = 74735
    • bytes = 118641472
  • DataInputReadFully

    • tiempo = 8953
    • bytes = 118641472
  • MemoryMapped

    • tiempo = 2320
    • bytes = 118641472

Aquí está el código ...

import java.io.BufferedInputStream; import java.io.DataInputStream; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.nio.MappedByteBuffer; import java.nio.channels.FileChannel; import java.nio.channels.FileChannel.MapMode; import java.util.HashSet; import java.util.Set; public class Main { public static void main(final String[] argv) { ArrayTest.main(argv); ArrayTest.main(argv); DataInputByteAtATime.main(argv); DataInputReadFully.main(argv); MemoryMapped.main(argv); } } abstract class Test { public final void run(final File root) { final Set<File> files; final long size; final long start; final long end; final long total; files = new HashSet<File>(); getFiles(root, files); start = System.currentTimeMillis(); size = readFiles(files); end = System.currentTimeMillis(); total = end - start; System.out.println(getClass().getName()); System.out.println("time = " + total); System.out.println("bytes = " + size); } private void getFiles(final File dir, final Set<File> files) { final File[] childeren; childeren = dir.listFiles(); for(final File child : childeren) { if(child.isFile()) { files.add(child); } else { getFiles(child, files); } } } private long readFiles(final Set<File> files) { long size; size = 0; for(final File file : files) { size += readFile(file); } return (size); } protected abstract long readFile(File file); } class ArrayTest extends Test { public static void main(final String[] argv) { final Test test; test = new ArrayTest(); test.run(new File(argv[0])); } protected long readFile(final File file) { InputStream stream; stream = null; try { final byte[] data; int soFar; int sum; stream = new BufferedInputStream(new FileInputStream(file)); data = new byte[(int)file.length()]; soFar = 0; do { soFar += stream.read(data, soFar, data.length - soFar); } while(soFar != data.length); sum = 0; for(final byte b : data) { sum += b; } return (sum); } catch(final IOException ex) { ex.printStackTrace(); } finally { if(stream != null) { try { stream.close(); } catch(final IOException ex) { ex.printStackTrace(); } } } return (0); } } class DataInputByteAtATime extends Test { public static void main(final String[] argv) { final Test test; test = new DataInputByteAtATime(); test.run(new File(argv[0])); } protected long readFile(final File file) { DataInputStream stream; stream = null; try { final int fileSize; int sum; stream = new DataInputStream(new BufferedInputStream(new FileInputStream(file))); fileSize = (int)file.length(); sum = 0; for(int i = 0; i < fileSize; i++) { sum += stream.readByte(); } return (sum); } catch(final IOException ex) { ex.printStackTrace(); } finally { if(stream != null) { try { stream.close(); } catch(final IOException ex) { ex.printStackTrace(); } } } return (0); } } class DataInputReadFully extends Test { public static void main(final String[] argv) { final Test test; test = new DataInputReadFully(); test.run(new File(argv[0])); } protected long readFile(final File file) { DataInputStream stream; stream = null; try { final byte[] data; int sum; stream = new DataInputStream(new BufferedInputStream(new FileInputStream(file))); data = new byte[(int)file.length()]; stream.readFully(data); sum = 0; for(final byte b : data) { sum += b; } return (sum); } catch(final IOException ex) { ex.printStackTrace(); } finally { if(stream != null) { try { stream.close(); } catch(final IOException ex) { ex.printStackTrace(); } } } return (0); } } class DataInputReadInChunks extends Test { public static void main(final String[] argv) { final Test test; test = new DataInputReadInChunks(); test.run(new File(argv[0])); } protected long readFile(final File file) { DataInputStream stream; stream = null; try { final byte[] data; int size; final int fileSize; int sum; stream = new DataInputStream(new BufferedInputStream(new FileInputStream(file))); fileSize = (int)file.length(); data = new byte[512]; size = 0; sum = 0; do { size += stream.read(data); sum = 0; for(int i = 0; i < size; i++) { sum += data[i]; } } while(size != fileSize); return (sum); } catch(final IOException ex) { ex.printStackTrace(); } finally { if(stream != null) { try { stream.close(); } catch(final IOException ex) { ex.printStackTrace(); } } } return (0); } } class MemoryMapped extends Test { public static void main(final String[] argv) { final Test test; test = new MemoryMapped(); test.run(new File(argv[0])); } protected long readFile(final File file) { FileInputStream stream; stream = null; try { final FileChannel channel; final MappedByteBuffer buffer; final int fileSize; int sum; stream = new FileInputStream(file); channel = stream.getChannel(); buffer = channel.map(MapMode.READ_ONLY, 0, file.length()); fileSize = (int)file.length(); sum = 0; for(int i = 0; i < fileSize; i++) { sum += buffer.get(); } return (sum); } catch(final IOException ex) { ex.printStackTrace(); } finally { if(stream != null) { try { stream.close(); } catch(final IOException ex) { ex.printStackTrace(); } } } return (0); } }