Moviéndonos entre archivos con python

miércoles, 21 de enero de 2015


 A veces, cuando tratamos con archivos necesitamos algo más que sólo leer todo el archivo. Necesitamos poder movernos entre el archivo y leer partes que bien podrían resultar aleatorias. En esta entrada veremos esos métodos que nos brinda Python para conseguir ¡movernos entre los archivos!

 

Abriendo el archivo


Python nos da dos opciones para abrir un archivo:

archivo = open(ruta_archivo, modo_apertura)  # Abrimos el archivo
archivo.read()
archivo.close()  # Cerramos el archivo

with open(ruta_archivo, modo_apertura) as archivo:  # Abrimos el archivo
    print archivo.read() 


En la primer forma nos tenemos que preocupar por cerrar el archivo, en la segunda forma, cuando salimos del bloque with Python se encarga de cerrar el archivo por nosotros. Ambas formas retornan un objeto tipo file.

Modos de apertura


Modo apertura Significado
r Abre el archivo en modo sólo lectura.
w Abre el archivo en modo sólo escritura. Si ya existe el archivo éste se sobrescribe; de lo contrario, se crea el archivo.
a Abre el archivo en modo escritura. Si el archivo ya existe se escribe la información al final.
r+ Abre el archivo en los modos lectura y escritura.
rb Abre el archivo en modo sólo lectura binaria.
rw Abre el archivo en modo sólo escritura binaria.
r+b Abre el archivo en los dos modos lectura y escritura binaria.

En Windows se distingue entre archivos de texto y archivos binarios. Así que debemos tener cuidado con el modo en el que abrimos los archivos.

with open("data.txt", "w") as archivo:  # Abrimos el archivo en modo escritura
    print archivo.write("Hola mundo")  # Escribimos en el archivo

En el script anterior abrimos el archivo data.txt y escribimos en el "Hola mundo"

Métodos del objeto file


Leyendo el archivo


archivo.read([tamaño])

El argumento tamaño es opcional y determina la cantidad de bytes que van a ser leídos. Si no se especifica, se leerá todo el archivo.
archivo.readline()

El método readline() nos permite leer sólo una línea del archivo.
arhivo.readlines()

El método readlines() lee todo el archivo y regresa una lista donde cada elemento es una línea del archivo.

Cada que leemos en el archivo también nos movemos en él, así, la próxima vez que leamos lo haremos un byte a la derecha desde la última posición.

Cuando llegamos al final del archivo, la lectura nos devolverá una cadena vacía.

Leyendo la versión de un PDF

La cabecera de los archivos PDF tienen el formato: %PDF-1.N(EOL)

Donde N es un número que puede ir desde uno hasta siete y representa la especificación y (EOL) representa un final del línea que puede ser un retorno de carro, una línea nueva o ambas.

Así pues,  tenemos dos opciones para leer la versión de un archivo PDF.

with open("pdf.pdf", "r") as archivo:  # Abrimos el archivo
    print archivo.readline()  # Leemos la primer línea

Leemos la primer línea completa del archivo.
%PDF-1.4\n

with open("pdf.pdf", "r") as archivo:  # Abrimos el archivo
    print archivo.read(8)  # Leemos los primeros ocho bytes del archivo

Sólo leemos los primeros ocho bytes del archivo.
%PDF-1.4

Otros métodos del objeto file


Conocer la posición en el archivo

Como ya se explicó antes, cada que leemos el archivo, también nos movemos en el, con el método tell() Python nos permite conocer la posición (el byte) donde estamos en el archivo.
with open("pdf.pdf", "r") as archivo:  # Abrimos el archivo
    print "Posición inicial:", archivo.tell()
    print "Cabecera:", archivo.read(8)
    print "Posición final:", archivo.tell()

Posición inicial: 0
Cabecera: %PDF-1.4
Posición final: 8

Moviéndonos entre el archivo


archivo.seek(bytes, [desde_donde])

El argumento bytes indica la cantidad de bytes que nos vamos a mover dentro del archivo.

El argumento desde_donde es opcional, puede tomar tres valores 0, 1 y 2 e indica desde donde nos vamos a mover. 0 (valor por defecto) indica que nos vamos a mover desde el principio del archivo. 1 indica que nos vamos a mover desde donde se encuentra actualmente el puntero. 2 indica que nos vamos a mover desde el final del archivo.

Si el argumento desde_donde es especificado y es distinto que 0, entonces el argumento bytes puede tomar valores negativos y positivos. Un valor positivo indica que nos vamos a mover hacía la derecha y un valor negativo indica que nos vamos a mover hacía la izquierda.

Leyendo un archivo desde atrás

A veces necesitamos leer los archivos desde atrás ya sea porque las especificaciones así lo requieren (como en el formato PDF) o porque lo que nos interesa está ahí ej. los típicos casos de esteganografía por EOF (End Of File) donde la información que queremos ocultar la guardamos al final de una imagen. Si no pudiéramos movernos entre el archivo, tendríamos que leer todo el archivo y luego sí leer la parte que necesitamos.

Para este ejemplo vamos a usar la imagen principal de la entrada que guardaremos como "moviendonos.png". He guardado un pequeño mensaje ahí que ocupa los últimos 26 bytes.

with open("moviendonos.png", "r") as archivo:  # Abrimos el archivo
    archivo.seek(1, 2)  # Nos movemos al final del archivo
    buffer = ""
    for _ in xrange(26):  # Recorremos los 26 bytes
        archivo.seek(-2, 1)  #  Nos movemos dos bytes a la izquierda
        buffer += archivo.read(1)  # Leemos un byte

print buffer

Recordemos que cuando leemos el archivo sin importar el método que usemos, Python comenzará a leer desde el byte a la derecha de donde se encuentra el puntero. Por eso en la quinta línea nos movemos dos bytes a la izquierda y cuando leemos en la sexta línea nos movemos un byte a la derecha.

El resultado es:


elblogdeonce.blogspot.com

Por lo general se usa un "separador" para delimitar donde acaba el archivo original y comienza nuestro mensaje; así que si no conocemos la cantidad de bytes que tiene el mensaje escondido, podemos seguir leyendo hasta que encontremos el separador. Teniendo en cuenta que como estamos leyendo desde atrás, el mensaje también lo estaremos leyendo desde atrás.

Si abrimos la imagen con un editor hexadecimal podemos ver que el mensaje está escrito al revés. Por eso cuando lo leemos es legible.


Saludos!
Once

No hay comentarios:

Publicar un comentario