Aunque ya había mirado como leer y escribir ficheros en python hace tiempo, con el tema del curso de python con el que estoy entretenido en la chuwiki, lo he estado revisando. Y ¿cómo no?, he encontrado un par de cosas que me han llamado la atención sólo porque son diferentes en java.
La primera es cómo saber si hemos llegado al final del fichero cuando hacemos un bucle para leerlo. En java, el método readLine() devuelve un null y hay que poner un if del estilo
while (null!=linea) {
...
}
En python, devuelve una cadena vacía. Esto es así porque el método readLine() de python devuelve los retornos de carro, así que una línea en blanco devolvería ‘\n’, mientras que en java devolvería una cadena vacía ». Y en python, para el bucle, tienes otra forma de hacerlo
while linea:
...
No hace falta compararlo con nada. Los condicionales de python son listos y si la cadena está vacía o es None, devuelve false. Aunque es diferente de java y me ha llamado la atención, este tipo de condicionales que dan false si la cadena está vacía o es None, no me ha llamado tanto la atención, puesto que javascript también funciona así.
Aquí sólo un apunte. En python me parece engorroso que al leer una línea me devuelva también el retorno de carro final. Java se lo come y no te lo devuelve. No sé qué es más útil, pero me da la impresión de que si la línea contiene campos que quieres extaer, estilo fichero CSV, el retorno de carro al final vas a tener que eliminarlo con código.
Y lo segundo que me ha llamado mucho más la atención es que el descriptor de un fichero abierto de python es un iterator. Por lo que iterando sobre él vamos leyendo. Podemos incluso meterlo en un bucle. En java, para leer un fichero hasta el final necesitamos algo tan engorroso coom esto
String linea = bufferedRead.readLine();
while (null!=linea) {
// tratar la línea
linea = bufferedReader.readLine();
}
es decir, dos lecturas, una antes de entrar en el bucle para tener la variable línea inicializada con la primera línea del fichero y luego, dentro del bucle, como última línea, otra lectura. Este tipo de estructuras siempre me ha parecido poco elegante por lo de hacer dos lecturas. Con un do-while tampoco podemos hacerlo con una lectura.
Sin embargo, en python, como el fichero abierto es un iterator, podemos hacer esto
f = open ('fichero.txt')
for linea in f:
# Tratar la línea.
Mucho más claro. Funciona igual con ficheros de texto o binarios. Si lo abres como texto devuelve líneas, si lo tratas como binario devuelve bytes. Y ni siquiera hace falta la comparación para saber si hemos llegado a final de fichero.
Punto para python 🙂
ACTUALIZACION: Tras el comentario de GreenEyed, actualizo el post. No es necesario poner dos líneas de lectura en el código java «tradicional», basta con meterlo todo en el paréntesis del while
String line;
while ( (line = bufferedReader.readLine()) != null) {
// tratar línea
}
y a partir de java 8 hay más opciones para leer el fichero como se ve en el enlace que pone en el comentario.
Por romper una lanza en favor de Java, desde Java 8, que ya tiene años, hay formas de leer ficheros linea a linea sin tener que hacer la doble lectura. Aquí mismo (https://mkyong.com/java8/java-8-stream-read-a-file-line-by-line/) hay varias formas de hacerlo, comparadas con las clásicas formas de hacerlo con varias lecturas.
Así que ya solo queda sobre eso el tratamiento de excepciones/cerrar el Stream para no tener un leak :P.
Un saludo
Cierto, me he quedado anclado en el pasado.
Es más, en el enlace que me has pasado, el punto «4. Classic BufferedReader and Scanner», ni siquiera hay que irse a cosas «modernas» de java 8 🙂