Leer un archivo línea por línea en Java

L

En Ciencias de la Computación, un archivo es un recurso que se utiliza para registrar datos discretamente en el dispositivo de almacenamiento de una computadora. En Java, un recurso suele ser un objeto que implementa el AutoCloseable interfaz.

La lectura de archivos y recursos tiene muchos usos:

  • Estadísticas, análisis e informes
  • Machine Learning
  • Manejo de registros o archivos de texto grandes

A veces, estos archivos pueden ser absurdamente grandes, con gigabytes o terabytes almacenados, y leerlos en su totalidad es ineficaz.

Poder leer un archivo línea por línea nos da la capacidad de buscar solo la información relevante y detener la búsqueda una vez que hayamos encontrado lo que estamos buscando. También nos permite dividir los datos en partes lógicas, como si el archivo tuviera formato CSV.

Hay algunas opciones diferentes para elegir cuando necesita leer un archivo línea por línea.

Escáner

Una de las formas más fáciles de leer un archivo línea por línea en Java podría implementarse utilizando el Escáner clase. Un escáner divide su entrada en tokens usando un patrón delimitador, que en nuestro caso es el carácter de nueva línea:

Scanner scanner = new Scanner(new File("filename"));
while (scanner.hasNextLine()) {
   String line = scanner.nextLine();
   // process the line
}

los hasNextLine() devuelve el método true si hay otra línea en la entrada de este escáner, pero el escáner en sí no avanza más allá de ninguna entrada ni lee ningún dato en este punto.

Para leer la línea y seguir adelante, debemos usar el nextLine() método. Este método hace avanzar el escáner más allá de la línea actual y devuelve la entrada que no se alcanzó inicialmente. Este método devuelve el resto de la línea actual, excluyendo cualquier separador de línea al final de la línea. La posición de lectura se establece al principio de la siguiente línea, que se leerá y devolverá al llamar al método nuevamente.

Dado que este método continúa buscando a través de la entrada buscando un separador de línea, puede almacenar en búfer toda la entrada mientras busca el final de la línea si no hay separadores de línea presentes.

Lector en búfer

los BufferedReader La clase representa una forma eficiente de leer los caracteres, matrices y líneas de un flujo de entrada de caracteres.

Como se describe en la denominación, esta clase usa un búfer. La cantidad predeterminada de datos que se almacenan en búfer es de 8192 bytes, pero se puede establecer en un tamaño personalizado por razones de rendimiento:

BufferedReader br = new BufferedReader(new FileReader(file), bufferSize);

El archivo, o más bien una instancia de un File clase, no es una fuente de datos apropiada para el BufferedReader, entonces necesitamos usar un FileReader, que se extiende InputStreamReader. Es una clase de conveniencia para leer información de archivos de texto y no es necesariamente adecuada para leer un flujo de bytes sin procesar:

try (BufferedReader br = new BufferedReader(new FileReader(file))) {
    String line;
    while ((line = br.readLine()) != null) {
       // process the line
    }
}

La inicialización de un lector con búfer se escribió utilizando la sintaxis try-with-resources, específica de Java 7 o superior. Si está utilizando una versión anterior, debe inicializar el br variable antes de la try declaración y ciérrelo en el finally bloquear.

A continuación, se muestra un ejemplo del código anterior sin la sintaxis try-with-resources:

BufferedReader br = new BufferedReader(new FileReader(file));
try {
    String line;
    while ((line = br.readLine()) != null) {
       // process the line
    }
} finally {
    br.close();
}

El código recorrerá las líneas del archivo proporcionado y se detendrá cuando se encuentre con el null línea, que es el final del archivo.

No se confunda como el null no es igual a una línea vacía y el archivo se leerá hasta el final.

El método de las líneas

UN BufferedReader la clase también tiene un lines método que devuelve un Stream. Esta secuencia contiene líneas que fueron leídas por el BufferedReader, como sus elementos.

Puede convertir fácilmente esta secuencia en una lista si necesita:

List<String> list = new ArrayList<>();

try (BufferedReader br = new BufferedReader(new FileReader(file))) {
    list = br.lines().collect(Collectors.toList());    
}

Leer esta lista es lo mismo que leer una secuencia, que se tratan en la siguiente sección:

list.forEach(System.out::println);

Secuencias de Java 8

Si ya está familiarizado con Java 8 Corrientes, puede usarlos como una alternativa más limpia al ciclo heredado:

try (Stream<String> stream = Files.lines(Paths.get(fileName))) {
    stream.forEach(System.out::println);
}

Aquí estamos usando la sintaxis try-with-resources una vez más, inicializando un flujo de líneas con el Files.lines() método auxiliar estático. los System.out::println La referencia de método se usa para propósitos de demostración, y debe reemplazarla con cualquier código que esté usando para procesar sus líneas de texto.

Además de una API limpia, las transmisiones son muy útiles cuando desea aplicar múltiples operaciones a los datos o filtrar algo.

Supongamos que tenemos una tarea para imprimir todas las líneas que se encuentran en un archivo de texto dado y terminan con el carácter “/”. Las líneas deben transformarse a mayúsculas y ordenarse alfabéticamente.

Al modificar nuestro ejemplo inicial de “Streams API” obtendremos una implementación muy limpia:

try (Stream<String> stream = Files.lines(Paths.get(fileName))) {
    stream
        .filter(s -> s.endswith("/"))
        .sorted()
        .map(String::toUpperCase)
        .forEach(System.out::println);
}

los filter() El método devuelve una secuencia que consta de los elementos de esta secuencia que coinciden con el predicado dado. En nuestro caso, solo dejamos aquellos que terminan con “/”.

los map() El método devuelve una secuencia que consta de los resultados de aplicar la función dada a los elementos de esta secuencia.

los toUpperCase() método de un String La clase nos ayuda a lograr el resultado deseado y se utiliza aquí como referencia de método, al igual que la println llamada de nuestro ejemplo anterior.

los sorted() El método devuelve una secuencia que consta de los elementos de esta secuencia, ordenados según el orden natural. También puede proporcionar una Comparator, y en ese caso la clasificación se realizará de acuerdo con él.

Si bien el orden de las operaciones podría cambiarse para filter(), sorted()y map() métodos, el forEach() siempre debe colocarse al final, ya que es una operación de terminal. Vuelve void y de hecho, nada se le puede encadenar más.

Apache Commons

Si ya estás usando Apache Commons en su proyecto, es posible que desee utilizar el ayudante que lee todas las líneas de un archivo en un List<String>:

List<String> lines = FileUtils.readLines(file, "UTF-8");
for (String line: lines) {
    // process the line
}

Recuerde que este enfoque lee todas las líneas del archivo en el lines lista y sólo entonces la ejecución de la for comienza el bucle. Puede llevar una cantidad significativa de tiempo y debe pensarlo dos veces antes de usarlo en archivos de texto grandes.

Conclusión

Hay varias formas de leer un archivo línea por línea en Java, y la selección del enfoque apropiado es decisión del programador. Debe pensar en el tamaño de los archivos que planea procesar, los requisitos de rendimiento, el estilo del código y las bibliotecas que ya están en el proyecto. Asegúrese de probar en algunos casos de esquina, como archivos enormes, vacíos o inexistentes, y estará listo para usar cualquiera de los ejemplos proporcionados.

 

About the author

Ramiro de la Vega

Bienvenido a Pharos.sh

Soy Ramiro de la Vega, Estadounidense con raíces Españolas. Empecé a programar hace casi 20 años cuando era muy jovencito.

Espero que en mi web encuentres la inspiración y ayuda que necesitas para adentrarte en el fantástico mundo de la programación y conseguir tus objetivos por difíciles que sean.

Add comment

Sobre mi

Últimos Post

Etiquetas

Esta web utiliza cookies propias para su correcto funcionamiento. Al hacer clic en el botón Aceptar, aceptas el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos. Más información
Privacidad