1. Descripción general
Este tutorial demostrará cómo leer de manera eficiente archivos grandes en Java. Java - Regrese a lo básico.
2. Lea en la memoria
La forma estándar de leer líneas de archivo es leer en la memoria. Tanto Guava como ApacheCommonsio proporcionan métodos para leer rápidamente las líneas de archivo de la siguiente manera:
Files.readLines(new File(path), Charsets.UTF_8);
FileUtils.readLines(new File(path));
El problema con este método es que todas las líneas del archivo se almacenan en la memoria, y cuando el archivo es lo suficientemente grande, rápidamente hará que el programa arroje una excepción de MemoryError.
Por ejemplo: lea un archivo de aproximadamente 1g:
@Testpublic void dedusingguaVa_wheniteratingAfile_thenworks () lanza ioexception {string path = ... files.readlines (nuevo archivo (ruta), charsets.utf_8);}Este método ocupa solo una pequeña cantidad de memoria al principio: (consume aproximadamente 0 MB de memoria)
[Principal] Info org.baeldung.java.corejaviounittest - Memoria total: 128 MB [principal] Info org.baeldung.java.corejavaiounittest - memoria libre: 116 MB
Sin embargo, cuando todos los archivos se leen en la memoria, finalmente podemos ver (aproximadamente 2 GB de memoria se consume):
[Principal] Info org.baeldung.java.corejavaiounittest - Memoria total: 2666 MB [Main] Info org.baeldung.java.corejavaiounittest - Memoria libre: 490 MB
Esto significa que este proceso consume aproximadamente 2.1GB de memoria: la razón es simple: ahora todas las líneas del archivo se almacenan en la memoria.
Poner todo el contenido de un archivo en la memoria se extenderá rápidamente de la memoria disponible, sin importar cuán grande sea la memoria disponible, esto es obvio.
Además, generalmente no necesitamos poner todas las líneas del archivo en la memoria a la vez; en cambio, solo necesitamos atravesar cada línea del archivo, luego hacer el procesamiento correspondiente y tirarlo después del procesamiento. Entonces, eso es exactamente lo que vamos a hacer: iterar a través de filas, en lugar de poner todas las filas en la memoria.
3. Stream de archivo
Ahora veamos esta solución: usaremos la clase java.util.scanner para escanear el contenido del archivo y leerlo continuamente en línea:
FileInputStream inputStream = null; scanner sc = null; try {inputStream = new FileInputStream (PATH); Sc = New Scanner (InputStream, "UTF-8"); while (sc.hasnextline ()) {string line = sc.nextline (); // System.out.println (línea); } // Tenga en cuenta que el escáner suprime las excepciones if (sc.ioException ()! = NULL) {Throw sc.ioException (); }} finalmente {if (inputStream! = null) {inputStream.close (); } if (sc! = null) {sc.close (); }}Esta solución atravesará todas las líneas en el archivo, lo que permite procesar cada línea sin mantener una referencia a ella. De todos modos, no fueron almacenados en la memoria: (se consumieron alrededor de 150 MB de memoria)
[principal] infoorg.baeldung.java.corejaviounittest-totalmemory: 763mb
[principal] infoorg.baeldung.java.corejaviounittest-freememoria: 605mb
4. APACHECOMMONSIO Stream
También puede usar la Biblioteca Commonsio para implementarla, utilizando el LineIterator personalizado proporcionado por la biblioteca:
LineIterator it = fileUtils.lineIterator (theFile, "utf-8"); try {while (it.hasnext ()) {string line = it.nextline (); // hacer algo con línea}} Finalmente {LineIterator.Closequietty (It);}Dado que todo el archivo no se almacena en la memoria, esto conduce a un consumo de memoria bastante conservador: (se consume alrededor de 150 MB de memoria)
[principal] infoo.b.java.corejavaiointegrationtest-totalmemory: 752mb
[Main] infoo.b.java.corejavaiointegrationtest-freememoria: 564mb
5. Conclusión
Este breve artículo describe cómo procesar archivos grandes sin lectura repetida y salirse sin memoria; esto proporciona una solución útil para procesar archivos grandes.
Todos estos ejemplos se implementan y los fragmentos de código disponibles en mi proyecto GitHub: este es un proyecto basado en Eclipse, por lo que debe importarse y ejecutarse fácilmente.
Lo anterior es todo el contenido de este artículo sobre la lectura eficiente de Java de archivos grandes. Espero que sea útil para todos. Los amigos interesados pueden continuar referiéndose a otros temas relacionados en este sitio. Si hay alguna deficiencia, deje un mensaje para señalarlo. ¡Gracias amigos por su apoyo para este sitio!