8. Archivos: Datos en memoria secundaria

Contenidos

  1. Introducción a Archivos
  2. Creación de archivos
  3. Lectura de archivos por línea
  4. Lectura de archivos en listas
  5. Lectura de archivos completos
  6. Ejemplos
  7. Ejercicios

8.1 Introducción a Archivos

Durante la ejecución de un programa, los datos se mantienen almacenados en la memoria principal (RAM), que es sumamente rápida de leer y escribir. Pero también es volátil. Esto significa que cuando el programa termina o cuando apagamos el computador, el contenido de este memoria desaparece. Es por esto que para almacenar datos se utilizan medios de almacenamiento persistente, como los discos duros, las memorias USB, o un CD/DVD.

La manera de organizar los datos en los medios persistentes se consigue a través de unidades de datos llamadas archivos. Estos archivos poseen una ubicación particular dentro del medio persistente. Asimismo, los archivos poseen un nombre que permite al computador ubicar el conjunto de datos (archivo) deseado dentro del medio. La organización de estos archivos se consigue a través de un sistema que se conoce como sistema de archivos. Cada medio de almacenamiento utiliza un sistema de archivos (por ejemplo, NTFS, FAT, ext4, HFS) para organizar la ubicación de los archivos dentro del medio de almacenamiento y le permite al computador leer, modificar y escribir datos dentro de estos archivos.

Para poder trabajar con datos persistentes, los programas deben ser capaces de crear, eliminar, leer y escribir archivos. Python posee funciones que permiten hacer esta manipulación independientemente del sistema de archivos que esté utilizando el computador.

8.2 Creación de archivos

Crear un archivos es bastante fácil en Python. El lenguaje posee la instrucción open(filename, "w"), que permite crear un archivo nuevo y vacío, de nombre filename. El parámetro “w” (write) indica que el archivo debe crearse porque vamos a escribir en él. Si ya existe un archivo con el mismo nombre, este archivo es reemplazado completamente por el archivo que vamos a escribir.

Por ejemplo, el siguiente código:

un_archivo = open("prueba.txt", "w")
un_archivo.close()

Crear un archivo vacío de nombre “prueba.txt” y entrega como resultado un objeto que permite manipular los contenidos del archivo. El método close se utiliza para indicar que ya no ocuparemos el archivo y que por lo tanto el sistema puede liberar los recursos que tenía asignado a él.

Pero hasta ahora no hemos hecho nada con el contenido del archivo. Para escribir algo en él, utilizamos el método write, que funciona de manera similar a la función print, pero write escribe un string en el archivo sobre el cual se invoca.

El siguiente ejemplo,

un_archivo = open("prueba.txt", "w")
un_archivo.write("Mi primer archivo\n")
un_archivo.write("-----------------\n")
un_archivo.write("Estamos escribiendo texto\n")
un_archivo.write("Dentro de un archivo nuevo.")
un_archivo.write("Y este texto no ha cambiado de línea.")
un_archivo.close()

Crear un archivo nuevo prueba.txt, inicialmente vacío (si el archivo existía, se borra su contenido), y escribe en él cada uno de los textos indicados por write. Notemos que, a diferencia de print, el método write no agrega un cambio de línea al final de cada ejecución. Por ello, si queremos agregar un cambio de línea, debemos agregar el caracter \n al final de cada texto. De esta manera el código anterior escribe el siguiente contenido en prueba.txt

Mi primer archivo
-----------------
Estamos escribiendo texto
Dentro de un archivo nuevo.Y este texto no ha cambiado de línea.

8.3 Lectura de archivos por línea

Además de escribir archivos, también necesitamos leer su contenido. Para leer el contenido de un archivo, lo primero que debemos hacer abrirlo. Para esto se usa la misma función open(filename, "r"), pero ahora el segundo argumento es “r” (read).

De esta manera, el código:

un_archivo = open("prueba.txt", "r")

retorna un objeto que puede ser utilizado para leer el contenido del archivo. Para leer efectivamente el contenido del archivo podemos usar el método readline(), el cual retorna una línea completa (string) del archivo.

El siguiente código:

un_archivo = open("prueba.txt", "r")
una_linea = un_archivo.readline()
while len(una_linea) != 0:
  print("Leimos: ", una_linea)
  una_linea = un_archivo.readline()
un_archivo.close()

abre el archivo prueba.txt, y lee una línea. Luego entra en un ciclo en que continúa leyendo e imprimiendo en pantalla una línea del archivo a la vez. El ciclo termina cuando el resultado de la lectura es una línea vacía, esto es un string igual a "".

Notemos que cada línea leída de un archivo contiene al final el caracter \n. De esta manera si hay una línea vacía a lo largo del archivo, ésta no es leída como una línea vacía, sino como una línea que solo contiene \n, por lo tanto no cumple la condición para terminar el ciclo en este ejemplo.

Si tratamos de abrir un archivo inexistente, Python reporta un error de la siguiente manera:

otro_archivo = open("noExisto.txt", "r")
otro_archivo.close()
FileNotFoundError: [Errno 2] No such file or directory: 'noExisto.txt'

8.4 Lectura de archivos en listas

En ocasiones, en lugar de leer una línea a la vez, es conveniente leer todas las líneas de inmediato. Los objetos manipuladores de archivos poseen un métido para leer todoas líneas de un archivo y entregarlas como una lista de strings.

Si tenemos este archivo de nombre amigos.txt:

Monica
Sofía
Rafael
Jacinto
Belén
Abdul

El siguiente código:

amigos = open("amigos.txt", "r")
listaDeAmigos = amigos.readlines()
amigos.close()
listaDeAmigos.sort()
print(listaDeAmigos)

genera la salida:

['Abdul\n', 'Belen\n', 'Jacinto\n', 'Monica\n', 'Rafael\n', 'Sofia\n']

donde se encuentran todos los nombres del archivo amigos.txt ordenados. Notemos que al final de cada string se encuentra el caracter de fin de línea \n. Dependiendo de lo que queremos hacer, podemos eliminar este caracter de cada string al procesarlo usando el método strip('\n')

8.5 Lectura de archivos completos

Una manera adicional de leer archivos es leer todo el texto de una sola vez. El método read() permite guardar en un string todo el contenido del archivo. Si luego queremos separar el archivo de acuerdo a líneas, palabras, o algún caracter, podemos usar el método split().

El siguiente código

un_archivo = open("prueba.txt", "r")
contenido = un_archivo.read()
un_archivo.close()
print(contenido)
print("Caracteres en contenido:", len(contenido))
palabras = contenido.split()
print("Este archivo contiene",len(palabras),"palabras")

lee todo el contenido del archivo como un string muy largo con todo el contenido del archivo. Luego utiliza el método split() para separar de acuerdo a caracteres en blanco o cambios de línea, y entrega una lista de strings que almacenamos en palabras. El código genera la siguiente salida:

Mi primer archivo
-----------------
Estamos escribiendo texto
Dentro de un archivo nuevo.Y este texto no ha cambiado de línea.
Caracteres en contenido: 126
Este archivo contiene 19 palabras

8.6 Ejemplos

Ejemplo 8.1

El siguiente ejemplo lee un archivo y escribe en pantalla los contenidos de cada línea. Notar que al utilizar print aparece una línea en blanco. Esto ocurre debido a que cada línea incluye al final el caracter \n, y print siempre agrega un \n al final de cada invocación. Prueba reemplaza la línea print(l) por print(l, end=""). Haz un programa que imprima cada línea del archivo definido a continuación (mydata.txt).

Hydrogen
Helium
Lithium
Beryllium
Boron

Ejemplo 8.2

El siguiente ejemplo lee un archivo con nombres de persoas y edad separados por un espacio, e imprime todos los nombres ordenados alfabéticamente. Notar el uso de replace para eliminar los saltos de línea, y split para separa cada línea de acuerdo al espacio en blanco. El siguiente archivo contiene líneas con nombre de personas y su edad separados por un espacio. Hacer un programa que imprima todos los nombres ordenados alfabéticamente. El archivo se llama mydata2.txt.

Jose 20
Andres 23
Tomas 40
Pedro 14
Peter 33

Ejemplo 8.3

El siguiente ejemplo utiliza el mismo archivo, pero ahora imprime el promedio de las edades. La lectura es similar al ejemplo anterior, pero ahora luego del split se utiliza el elemento [1] de la lista. Para el ejemplo anterior, imprimir el promedio de las edades. El archivo ahora es mydata3.txt.

Jose 20
Andres 23
Tomas 40
Pedro 14
Peter 33

8.7 Ejercicios

A continuación, te proponemos varios ejercicios para que los resuelvas en tu libro interactivo.

Ejercicio 8.1

Para el ejemplo anterior, imprimir el nombre y la edad de la persona más joven y más vieja. El archivo se llama mydata4.txt.

Jose 20
Andres 23
Tomas 40
Pedro 14
Peter 33

Ejercicio 8.2

Hacer una función que recibe la ubicación de un archivo y retorna una lista de listas que contiene para cada palabra en el archivo, el número de apariciones. El archivo se llama mydata5.txt.

Lorem Ipsum Jose
Lorem Ipsum Camila
Hola Soy Una Palabra
Hola Lorem Ipsum Ipsum

Ejercicio 8.3

El siguiente archivo representa personas junto a sus calificaciones obtenidas en un curso. Imprimir cada persona del archivo junto a su promedio en el curso. El archivo se llama mydata6.txt

Jose-3.4,3.6,5.5
Camila-2.1,2.4,5.3
Tomas-2.2,3.3,4.4
Pedro-5.5,6.6,7.0
Dominga-7.0,7.0,3.0
Next Section - 9. Programación con Objetos y Clases