# XXXXXXXXXXXXXXXXPRO-UT3-A4. Operaciones con ficheros
## Elementos curriculares
---
* **Aramis Sarmiento Díaz y Richard Francisco Vaca Garcia, 1ro CFGS DAW**
---
**RA 5**. Realiza operaciones de entrada y salida de información, utilizando procedimientos específicos del lenguaje y librerías de clases.
**Criterios de evaluación**
c) Se han reconocido las posibilidades de entrada / salida del lenguaje y las librerías asociadas.
d) Se han utilizado ficheros para almacenar y recuperar información.
e) Se han creado programas que utilicen diversos métodos de acceso al contenido de los ficheros.
**Contenidos**
5. Lectura y escritura de información:
* Tipos de flujos. Flujos de bytes y de caracteres.
* Clases relativas a flujos.
* Utilización de flujos.
* Salida a pantalla.
* Ficheros de datos. Registros.
* Apertura y cierre de ficheros. Modos de acceso.
* Escritura y lectura de información en ficheros.
* Utilización de los sistemas de ficheros.
## Descripcioón de la Actividad
* **Metodología**: Investigación guiada coopertiva
* **Agrupamiento**: Parejas
* **Tiempo esperado**: 120 minutos
* **Producto**: Documento `md` (markdown) que se exportará a **PDF** para su entrega en la plataforma
* **Enunciado**:
* Elabora unos apuntes en los que se completarán los apartados que se especificarán a continuación.
* Las preguntas que se plantean **no deben contestarse directamente ni incluirse en los apuntes**, sino que se incluyen en el enunciado de la actividad para usarlas como **guía** de los contenidos que deberían aparecer en los apuntes.
* En cada apartado se incluirá código de ejemplo y el resultado de ejecutarlo. Así como explicación del mismo.
* Incluir un apartado final **Referencias** en el que se citarán todas las fuentes utilizadas
## Evaluación
* **Redacción**:
* El texto tiene **toda la información**. El registro y el tipo de texto son adecuados. Se agrega información que enriquece el tema.
* El texto está dividido en párrafos y cada uno responde a una idea. La explicación de las ideas es clara. El texto está organizado.
* La puntuación es correcta. Enlaza bien las ideas. Utiliza adecuadamente las estructuras morfosintácticas.
* Usa un vocabulario correcto y variado, sin repeticiones.
* Uso de ejemplos:
* Se usa correctamente el formato **markdown** para mostrar el código.
* Se muestra el resultado de ejecutar el código
* Se explican los aspectos relevantes del código de ejemplo.
* **Fuentes**:
* Al final del archivo se incluye un apartado **Referencias** en el que se enumeran las fuente de la que se obtuvo la información. Las fuentes son variadas y son rigurosas.
* El texto del enlace a las fuentes debe incluir el nombre de la web a la que apunta y una breve descrición de que nos vamos a encontrar al hacer clic en el mismo y . Ejemplo: [parzibyte.me: Diferencia entre lenguajes fuertemente y débilmente tipados](https://parzibyte.me/blog/2017/10/13/tipado-debil-tipado-fuerte-diferencias-explicacion/)
* **Trabajo en grupo**:
* Los apartados se elaboran de forma cooperativa poniéndose de acuerdo en cada uno de la información a incluir
* Todos los miembros del grupo colaboran de forma activa en la resolución de la tarea.
* Se ha previsto el tiempo necesario y se ha cumplido con el plazo previsto.
## Apartados
### 1. Ficheros
* **El objeto File en Python representa un fichero** del sistema operativo. Los ficheros sirven para guardar datos en disco que podrán ser leídos posteriormente.
* Los ficheros **son enormemente importantes en programación**. No solo debido al hecho evidente de que brindan el soporte que permite la mera existencia de las aplicaciones en el disco duro. La existencia del fichero hace posible que, al terminar una sesión de trabajo, se almacenen los datos y resultados en el disco, para poder retomar la tarea en una sesión posterior.
* Existen **dos tipos de ficheros: ficheros de texto y ficheros binarios**. Un fichero de texto contiene caracteres que son legibles por el ser humano y están guardados con una codificación (ASCII, UTF-8, …). Por el contrario, un fichero binario está compuesto por un flujo de bytes y solo tienen sentido para los programas o aplicaciones para los que son creados. Un ejemplo de este tipo de archivos son las imágenes o la música.
Cuando se trabaja con un fichero de texto, hay que tener en cuenta que este se estructura como una secuencia de líneas. Cada una de estas líneas acaba con un carácter especial conocido como EOL (fin de línea). En función del sistema operativo, este carácter puede variar. Puede ser **\n** (Unix) o **\r\n** (Windows).
* No obstante, en Python, cuando escribimos o leemos el carácter **\n** en un fichero de texto, el propio lenguaje se encarga de convertir dicho carácter al correspondiente por el sistema operativo, por lo que es algo a prever si nuestro código se va a ejecutar en diferentes sistemas.
**Ejemplo:**
```python=
# Leyendo del fichero "valores_en_columna.txt" línea a línea
fich_ent = open('valores_en_columna.txt', 'r') # Apertura
for linea in fich_ent:
print(linea)
fich_ent.close() # Cierre
# Resultado:
1
2
3
4
5
6
7
8
9
10
```
---
### 2. Apertura de ficheros en Python
* **Los diferentes modos en los que se puede abrir un fichero son:**
**"r":** Solo lectura. El fichero solo se puede leer. Es el modo por defecto si no se indica.
**"w":** Solo escritura. En el fichero solo se puede escribir. Si ya existe el fichero, machaca su contenido.
**"a":** Adición. En el fichero solo se puede escribir. Si ya existe el fichero, todo lo que se escriba se añadirá al final del mismo.
**"x":** Como ‘w’ pero si existe el fichero lanza una excepción.
**"r+":** Lectura y escritura. El fichero se puede leer y escribir.
* Todos estos modos abren el fichero en modo texto. Su versión correspondiente para abrir el fichero en modo binario sería: **"rb"**, **"wb"**, **"ab"**, **"xb"**, **"rb+"**.
* **Para escribir en un fichero o simplemente leer su contenido utilizaremos la función predefinida open().** Al invocar a esta, se crea un objeto de tipo File.
Lo más común es llamar a la función **open()** con dos parámetros:
* El primero de ellos es la ruta del fichero (en la que está o donde se va a crear).
* El segundo es el modo en el que se abre el fichero: lectura, escritura, …
Por defecto, cuando se invoca a la función **open(path, modo)**, el fichero se abre en modo texto. Si quisiéramos abrir un fichero en forma binaria, habría que añadir el carácter **"b"** al parámetro modo.
* **Codificación (Encoding):** Es el formato de codificación del archivo que se abrirá
Al leer el archivo, si la codificación es incorrecta, se informará un error.
* filename = 'data.csv' (el formato de codificación del archivo es utf-8)
* abierto (nombre de archivo, codificación = 'gbk') (la codificación gbk se usa cuando se llama a la función)
Aparecerá un error similar al siguiente:
```python=
UnicodeDecodeError: 'gbk' codec can't decode byte 0xac in position 423: illegal multibyte sequence
```
La forma correcta de abrir es:
* open(filename,encoding=‘utf-8’)
Si no se especifica el formato de codificación durante la lectura, el método de codificación devuelto por la función **locale.getpreferredencoding()** se utiliza de forma predeterminada.
* **Otros Ejemplos:**
Desde el explorador de archivos crea un fichero de nombre `archivo.txt` e introduce en el mismo algunas líneas de texto.
A continuación, en la misma carpeta se crea un fichero de python que contiene:
```python=
f = open("archivo.txt")
print(f)
```
El resultado de ejecutar el programa es el siguiente:
```python=
<_io.TextIOWrapper name='archivo.txt' mode='r' encoding='UTF-8'>
```
Esto sucede debio a que es necesario incluir el metodo de **"read()"** para poder leer el contenido.
---
### 3. Cierre de ficheros. El método `close()`
* La forma preferida para cerrar un archivo es usando el método del tipo objeto file llamado **close()**. Es necesario **cerrar un fichero despues de ser utilizado** por un programa por las siguientes razones:
* La escritura/lectura se realiza sobre los búferes y estos son eventualmente transferidos al medio físico. Cuando se cierra el fichero, se fuerza a realizar esa transferencia. De otro modo, se podría incurrir en pérdida de información.
* La utilización de un fichero comporta un consumo importante de memoria del ordenador (búferes y otros elementos). Si no se cierra el fichero, esa memoria resulta inutilizada.
* El Sistema Operativo establece un número máximo de ficheros que pueden estar abiertos simultáneamente. Si no cerramos los ficheros que, de momento, no estamos utilizando, puede que nuestro programa no pueda abrir otros que sí son necesarios.
* **Existen 3 formas de abrir/cerrar un fichero:**
* **1)** Abrir con la función **open()**: Como primer parámetro, se pasa el nombre del fichero y como segundo parámetro una cadena con caracteres similares a los de **fopen()** de **C**. Aquí se encuentran algunos **ejemplos:**
```python=
# Abrir fichero de lectura:
f = open("fichero.txt", "r")
```
```python=
# Abrir fichero de lectura en binario:
f = open("fichero.txt", "rb")
```
```python=
# Abrir fichero para escribir desde cero:
f = open ("fichero.txt", "w")
```
```python=
# Abrir fichero para añadir al final :
f = open ("fichero.txt", "a")
```
Para cerrarlo, basta llamar a **f.close()**.
* **2)** En Python, podemos poner código que puede tener problemas en tiempo de ejecución **try**. En el bloque de código, en **try** Los bloques de código pueden ser seguidos por uno o más **except** para capturar posibles anomalías.
Por ejemplo, en el proceso de leer el archivo anterior, el archivo no se puede encontrar causará **FileNotFoundError**, especificar una codificación desconocida aumentará **LookupError**, y si el archivo no se puede decodificar de la manera especificada al leer el archivo, **UnicodeDecodeError** estamos en **try** seguido por **tresexcept** Se maneja estas tres anomalías diferentes por separado.
Finalmente, usamos **finally** como bloque de código para cerrar el archivo abierto y liberar recursos externos adquiridos en el programa. El código de bloque se ejecutará sin importar que el programa sea normal o anormal incluso si se llama **sys** o con modular **exit**, la función sale del entorno de Python. Los bloques **finally** se ejecutan porque el **exit** de la función es esencialmente una excepción elevada **SystemExit**.
Usualmente ponemos **finally** a los bloques que se denominan como "siempre ejecutan bloques de código" y son más adecuados para operaciones que liberan recursos externos. Si se decide que ya no es necesario **finally**, cierre el objeto de archivo en el bloque de código para liberar el recurso, o también se puede usar la sintaxis de contexto **with** para la palabra clave especifica del contexto del objeto de archivo, la cual libera automáticamente los recursos del archivo al salir del contexto. A continuación tenemos un ejemplo.
```python=
def main():
try:
with open('To oak.txt', 'r', encoding='utf-8') as f:
print(f.read())
except FileNotFoundError:
print('¡No se puede abrir el archivo especificado!')
except LookupError:
print('¡Se ha especificado una codificación desconocida!')
except UnicodeDecodeError:
print('¡Error al decodificar al leer el archivo!')
if __name__ == '__main__':
main()
```
* **3)** Las palabras reservadas **"with"** y **"as"** se introdujeron en Python 2.6 (publicado en septiembre de 2006, aunque estaban disponibles en Python 2.5 en el módulo __future__) para facilitar, entre otros, la forma de trabajar con ficheros.
Su sintaxis general es la siguiente:
```python=
with EXPRESIÓN as VARIABLE:
BLOQUE DE INSTRUCCIONES
```
En el caso de los ficheros, la expresión es una llamada a la función **open()** y la variable es la conexión con el fichero:
```python=
with open("FICHERO") as fichero:
BLOQUE DE INSTRUCCIONES
```
La función **open** puede tener varios argumentos. Los más importantes son:
```python=
with open("FICHERO", mode="MODO", encoding="CODIFICACIÓN") as fichero:
BLOQUE DE INSTRUCCIONES
```
- **"FICHERO"** es la ruta absoluta o relativa hasta el fichero.
- **"MODO"** indica si el fichero se abre para leer, escribir o ambas cosas y si se trata de un fichero de texto o binario. El modo predeterminado es lectura en modo texto.
- **"CODIFICACIÓN"** indica el juego de caracteres del fichero: **"utf-8"** (UTF-8), **"cp1252"** (ASCII para Europa occidental), etc.
* Aquí tenemos un ejemplo de fichero en el cual se intenta abrir un fichero que ya existe en modo **"x"**.
El uso de **"x"** hace que si el fichero ya existe, se devuelve un error. En el siguiente código creamos un fichero e inmediatamente después intentamos crear un fichero con el mismo nombre con la opción ‘x’. Por lo tanto se devolverá un error.
```python=
f = open("mi_fichero.txt", "w")
# f = open("mi_fichero.txt", "x")
# Error! Ya existe
```
---
### 4. Escritura en fichero. El método `write()`
* El método **write()** tiene la función de añadir contenido a un archivo.
**Ejemplo:**
```python=
# Abrimos el fichero.
fichero = open("datos_guardados.txt", 'w')
# Tenemos unos datos que queremos guardar.
lista = ["Manzana", "Pera", "Plátano"]
# Guardamos la lista en el fichero.
for linea in lista:
fichero.write(linea + "\n")
# Cerramos el fichero.
fichero.close()
```
* Para escribir un fichero de texto, **los modos de apertura** que se pueden utilizar son los siguientes:
**"w"**: Borra el fichero si ya existiese y crea uno nuevo con el nombre indicado.
**"a"**: Añadirá el contenido al final del fichero si ya existiese (*append* end Inglés).
**"x"**: Si ya existe el fichero, se devuelve un error.
* Cabe notar que **no añade salto de línea automáticamente**, para ello debemos añadir **"\n"** al final de la línea.
* **Aquí tenemos algunos ejemplos del método `write()`:**
-
```python=
fichero = open("datos_guardados.txt", 'w')
fichero.write("Contenido a escribir")
fichero.close()
```
-
```python=
# Abrimos el fichero
fichero = open("datos_guardados.txt", 'w')
# Tenemos unos datos que queremos guardar
lista = ["Manzana", "Pera", "Plátano"]
# Guardamos la lista en el fichero
for linea in lista:
fichero.write(linea + "\n")
# Cerramos el fichero
fichero.close()
```
---
### 5. Lectura de ficheros. El método `read()`
* El método **read()** imprime el contenido del fichero.
Si no le pasamos ningún parámetro a **read()**, lee todo el contenido del archivo. Por otro lado, si le pasamos como parámetro un entero a **read()**, lee el contenido del archivo hasta el byte indicado.
* Al abrir un fichero de texto en modo lectura ocurre lo siguiente:
```python=
with open("archivo.txt", "r") as f:
print(f.read())
print(f.read())
```
(Imprime todo el contenido del fichero de texto solo una vez.)
---
### Método `tell()`
* Para qué se utiliza
* Ejemplo de uso
El metodo tell () retorna la posición actual del puntero.
**Ejemplo:**
``` python =
archivo = open("remeras.txt", "r")
linea1 = archivo.readline()
mas = archivo.read(archivo.tell() * 2)
if archivo.tell() > 50:
archivo.seek(50)
```
Si el contenido de `archivo.txt` es:
```
Este es un fichero de texto de prueba
```
mostrar el resultado y explicar el siguiente programa:
```python
with open("archivo.txt", "r") as f:
print(f.read(10))
print(f.tell())
print(f.read(5))
print(f.tell())
print(f.read())
print(f.tell())
```
Resultado:
```python=
Este es un
10
fich
15
ero de texto de prueba
39
```
Con el método read lee el contenido del archivo hasta la longitud indicada y muestra el texto "Este es un", en la siguiente línea imprime la posición del puntero la cual estaría en la posición indicada en read, en la siguiente linea imprime los 5 bytes siguientes "fich" que van después del mostrado en la primera línea . Luego muestra la posición del puntero que sería mayor ya que se han leído 5 bytes más. En la siguiente línea al no indicarle la longitud al método read muestra el texto restante y por último muestra la posición actual del puntero
### Método `seek()`
Se utiliza para mover el puntero hacia el byte indicado
```python
with open("archivo.txt", "r") as f:
print(f.read())
f.seek(0)
print(f.read())
```
En la primera línea se abre el fichero con permiso de lectura, luego lee todo el contenido del fichero y lo imprime, en la segunda línea mueve el puntero hacia el byte 0 y por último vuelve a leer e imprimir el contenido del archivo.
Resultado:
```python=
Este es un fichero de texto de prueba
Este es un fichero de texto de prueba
```
### Uso de bucle `for` para leer fichero
Permite leer línea a línea el contenido del fichero
**Ejemplo:**
```python=
with open("archivo.txt","r") as f:
for linea in f:
print(linea)
```
### Métodos `readline()` y `readlines()`
El método readline() sirve para leer una línea del archivo y el método readlines() para leer todas las líneas del fichero
La diferencia es que el método readline() solo lee una línea del archivo y el método readlines() lee todas las líneas del fichero
**Ejemplos:**
```python=
archivo = open("remeras.txt", "r")
for linea in archivo.readlines():
print linea
```
```python=
archivo = open("remeras.txt", "r")
linea1 = archivo.readline()
print linea1
```
### Métodos `writelines()`
El método writelines() permite modificar el contenido del archivo, es decir escribirlo, para ello debemos tener permiso de escritura.
**Ejemplos:**
```python=
fichero = open("datos_guardados.txt", 'w')
lista = ["Manzana", "Pera", "Plátano"]
fichero.writelines(lista)
fichero.close()
# Se guarda
# ManzanaPeraPlátano
```
```python=
fichero = open("datos_guardados.txt", 'w')
lista = ["Manzana\n", "Pera\n", "Plátano\n"]
fichero.writelines(lista)
fichero.close()
# Se guarda
# Manzana
# Pera
# Plátano
```
# **Referencias**
[Método tell ()](https://pythones.net/archivos-en-python-3/#Metodo_Tell)
[Método seek(), readline(), readlines() ](https://uniwebsidad.com/libros/python/capitulo-9/metodos-del-objeto-file)
[Método writelines(), write(), read()](https://ellibrodepython.com/escribir-archivos-python)
[J2Logo: Ficheros en Python](https://j2logo.com/como-escribir-en-un-fichero-en-python/)
[UVa: Fundamentos de Ficheros](https://www2.eii.uva.es/fund_inf/python/notebooks/10_Ficheros/Ficheros.html)
[Covantec: Python Básico- Ficheros](https://entrenamiento-python-basico.readthedocs.io/es/latest/leccion7/archivos.html)
[ProgrammerClick: Encoding](https://programmerclick.com/article/43151471587/)
[AprendeConAlf: Ficheros](https://aprendeconalf.es/docencia/python/manual/ficheros/)
[McLibre: Ficheros](https://www.mclibre.org/consultar/python/lecciones/python-ficheros.html)
[AprendeConAlf: Ejercicios de Ficheros](https://aprendeconalf.es/docencia/python/ejercicios/ficheros/)
[ChuWiki: Leer y Escribir Ficheros](http://chuwiki.chuidiang.org/index.php?title=Leer_y_escribir_ficheros_en_python)
[AcervoLima: Abrir y Cerrar Ficheros](https://es.acervolima.com/como-abrir-y-cerrar-un-archivo-en-python/)
[LibroDePython: Leer Archivo Python](https://ellibrodepython.com/leer-archivos-python)
## Recursos
* [Comprobar si un fichero existe](https://linuxize.com/post/python-check-if-file-exists/)
###### tags: `pro` `ut4` `ficheros`