Skip to content

📚 Unidad 8. Manejo de Archivos

El manejo de archivos es fundamental para leer datos, guardar resultados y trabajar con información persistente.


8.1. Abrir y Cerrar Archivos

Función open()

# Sintaxis básica
archivo = open("nombre_archivo.txt", "modo")
# ... operaciones ...
archivo.close()  # Importante cerrar

Modos de Apertura

Modo Descripción
"r" Lectura (por defecto). Error si no existe
"w" Escritura. Crea archivo o sobrescribe
"a" Añadir. Escribe al final
"x" Creación exclusiva. Error si existe
"r+" Lectura y escritura
"w+" Escritura y lectura (sobrescribe)
"a+" Añadir y lectura
"b" Modo binario (añadir a otros: "rb", "wb")

Uso con with (Recomendado)

# El archivo se cierra automáticamente al salir del bloque
with open("archivo.txt", "r") as archivo:
    contenido = archivo.read()
    print(contenido)
# Aquí el archivo ya está cerrado

8.2. Lectura de Archivos

Leer Todo el Contenido

# Leer todo como string
with open("archivo.txt", "r") as f:
    contenido = f.read()
    print(contenido)

# Leer con codificación específica
with open("archivo.txt", "r", encoding="utf-8") as f:
    contenido = f.read()

Leer Línea por Línea

# Leer una línea
with open("archivo.txt", "r") as f:
    primera_linea = f.readline()
    segunda_linea = f.readline()
    print(primera_linea)
    print(segunda_linea)

# Leer todas las líneas como lista
with open("archivo.txt", "r") as f:
    lineas = f.readlines()
    print(lineas)  # ['línea1\n', 'línea2\n', ...]

# Iterar sobre líneas (más eficiente para archivos grandes)
with open("archivo.txt", "r") as f:
    for linea in f:
        print(linea.strip())  # strip() quita \n

Leer Cantidad Específica

with open("archivo.txt", "r") as f:
    # Leer primeros 100 caracteres
    primeros_100 = f.read(100)

    # Leer siguientes 50
    siguientes_50 = f.read(50)

Ejemplos Prácticos de Lectura

# Contar líneas de un archivo
with open("datos.txt", "r") as f:
    num_lineas = sum(1 for _ in f)
print(f"El archivo tiene {num_lineas} líneas")

# Buscar palabra en archivo
def buscar_palabra(archivo, palabra):
    with open(archivo, "r", encoding="utf-8") as f:
        for num_linea, linea in enumerate(f, 1):
            if palabra.lower() in linea.lower():
                print(f"Línea {num_linea}: {linea.strip()}")

buscar_palabra("texto.txt", "python")

# Leer archivo y procesar datos
with open("numeros.txt", "r") as f:
    numeros = [int(linea.strip()) for linea in f if linea.strip()]
    print(f"Suma: {sum(numeros)}")
    print(f"Media: {sum(numeros)/len(numeros)}")

8.3. Escritura de Archivos

Escribir Texto

# Sobrescribir archivo (o crear si no existe)
with open("salida.txt", "w", encoding="utf-8") as f:
    f.write("Primera línea\n")
    f.write("Segunda línea\n")

# Añadir al final
with open("salida.txt", "a", encoding="utf-8") as f:
    f.write("Línea añadida\n")

Escribir Múltiples Líneas

lineas = ["Línea 1", "Línea 2", "Línea 3"]

# Con writelines (no añade \n automáticamente)
with open("archivo.txt", "w") as f:
    f.writelines(linea + "\n" for linea in lineas)

# Con join
with open("archivo.txt", "w") as f:
    f.write("\n".join(lineas))

Ejemplos Prácticos de Escritura

# Crear informe
def crear_informe(datos, archivo_salida):
    with open(archivo_salida, "w", encoding="utf-8") as f:
        f.write("=" * 40 + "\n")
        f.write("        INFORME DE DATOS\n")
        f.write("=" * 40 + "\n\n")

        for i, dato in enumerate(datos, 1):
            f.write(f"{i}. {dato}\n")

        f.write(f"\nTotal: {len(datos)} elementos\n")

datos = ["Manzana", "Naranja", "Plátano"]
crear_informe(datos, "informe.txt")

# Registro de log
from datetime import datetime

def log(mensaje, archivo="app.log"):
    timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
    with open(archivo, "a", encoding="utf-8") as f:
        f.write(f"[{timestamp}] {mensaje}\n")

log("Aplicación iniciada")
log("Usuario conectado")
log("Error: archivo no encontrado")

8.4. Archivos CSV

CSV (Comma-Separated Values) es un formato común para datos tabulares.

Módulo csv

import csv

Leer CSV

import csv

# Leer como lista de listas
with open("datos.csv", "r", encoding="utf-8") as f:
    lector = csv.reader(f)
    for fila in lector:
        print(fila)  # ['valor1', 'valor2', ...]

# Leer como diccionarios (con encabezados)
with open("datos.csv", "r", encoding="utf-8") as f:
    lector = csv.DictReader(f)
    for fila in lector:
        print(fila)  # {'columna1': 'valor1', ...}
        print(fila["nombre"])  # Acceder por nombre de columna

Escribir CSV

import csv

# Escribir lista de listas
datos = [
    ["Nombre", "Edad", "Ciudad"],
    ["Ana", 25, "Madrid"],
    ["Luis", 30, "Barcelona"],
    ["María", 28, "Valencia"]
]

with open("personas.csv", "w", newline="", encoding="utf-8") as f:
    escritor = csv.writer(f)
    escritor.writerows(datos)  # Escribir todas las filas

# Escribir fila por fila
with open("personas.csv", "w", newline="", encoding="utf-8") as f:
    escritor = csv.writer(f)
    escritor.writerow(["Nombre", "Edad", "Ciudad"])  # Encabezado
    escritor.writerow(["Ana", 25, "Madrid"])
    escritor.writerow(["Luis", 30, "Barcelona"])

# Escribir desde diccionarios
personas = [
    {"nombre": "Ana", "edad": 25, "ciudad": "Madrid"},
    {"nombre": "Luis", "edad": 30, "ciudad": "Barcelona"}
]

with open("personas.csv", "w", newline="", encoding="utf-8") as f:
    campos = ["nombre", "edad", "ciudad"]
    escritor = csv.DictWriter(f, fieldnames=campos)
    escritor.writeheader()  # Escribir encabezados
    escritor.writerows(personas)

Delimitadores Personalizados

# Usar punto y coma como delimitador
with open("datos.csv", "r", encoding="utf-8") as f:
    lector = csv.reader(f, delimiter=";")
    for fila in lector:
        print(fila)

# Usar tabulador
with open("datos.tsv", "w", newline="") as f:
    escritor = csv.writer(f, delimiter="\t")
    escritor.writerow(["Col1", "Col2", "Col3"])

Ejemplo Completo: Sistema de Inventario

import csv
import os

ARCHIVO = "inventario.csv"

def inicializar():
    """Crea el archivo si no existe."""
    if not os.path.exists(ARCHIVO):
        with open(ARCHIVO, "w", newline="", encoding="utf-8") as f:
            escritor = csv.writer(f)
            escritor.writerow(["ID", "Producto", "Cantidad", "Precio"])

def leer_inventario():
    """Lee y muestra el inventario."""
    with open(ARCHIVO, "r", encoding="utf-8") as f:
        lector = csv.DictReader(f)
        productos = list(lector)

    if not productos:
        print("Inventario vacío")
        return

    print("\n" + "=" * 50)
    print(f"{'ID':<5} {'Producto':<20} {'Cantidad':<10} {'Precio':<10}")
    print("-" * 50)
    for p in productos:
        print(f"{p['ID']:<5} {p['Producto']:<20} {p['Cantidad']:<10} {p['Precio']:<10}")
    print("=" * 50)

def agregar_producto(id, nombre, cantidad, precio):
    """Añade un producto al inventario."""
    with open(ARCHIVO, "a", newline="", encoding="utf-8") as f:
        escritor = csv.writer(f)
        escritor.writerow([id, nombre, cantidad, precio])
    print(f"Producto '{nombre}' añadido")

# Uso
inicializar()
agregar_producto("001", "Laptop", 10, 999.99)
agregar_producto("002", "Mouse", 50, 29.99)
agregar_producto("003", "Teclado", 30, 79.99)
leer_inventario()

8.5. Archivos JSON

JSON (JavaScript Object Notation) es ideal para datos estructurados.

import json

Leer JSON

import json

# Desde archivo
with open("datos.json", "r", encoding="utf-8") as f:
    datos = json.load(f)
    print(datos)

# Desde string
json_str = '{"nombre": "Ana", "edad": 25}'
datos = json.loads(json_str)
print(datos["nombre"])  # Ana

Escribir JSON

import json

datos = {
    "nombre": "Ana",
    "edad": 25,
    "ciudades": ["Madrid", "Barcelona"],
    "activo": True
}

# A archivo
with open("datos.json", "w", encoding="utf-8") as f:
    json.dump(datos, f, indent=4, ensure_ascii=False)

# A string
json_str = json.dumps(datos, indent=4, ensure_ascii=False)
print(json_str)

Ejemplo: Configuración de Aplicación

import json
import os

ARCHIVO_CONFIG = "config.json"

CONFIG_DEFAULT = {
    "idioma": "es",
    "tema": "claro",
    "notificaciones": True,
    "max_resultados": 50
}

def cargar_config():
    """Carga configuración o crea archivo por defecto."""
    if os.path.exists(ARCHIVO_CONFIG):
        with open(ARCHIVO_CONFIG, "r", encoding="utf-8") as f:
            return json.load(f)
    else:
        guardar_config(CONFIG_DEFAULT)
        return CONFIG_DEFAULT.copy()

def guardar_config(config):
    """Guarda configuración en archivo."""
    with open(ARCHIVO_CONFIG, "w", encoding="utf-8") as f:
        json.dump(config, f, indent=4, ensure_ascii=False)

def actualizar_config(clave, valor):
    """Actualiza una opción de configuración."""
    config = cargar_config()
    config[clave] = valor
    guardar_config(config)
    print(f"Configuración actualizada: {clave} = {valor}")

# Uso
config = cargar_config()
print(f"Idioma actual: {config['idioma']}")

actualizar_config("tema", "oscuro")
actualizar_config("max_resultados", 100)

Ejemplo: Base de Datos Simple

import json
import os

class BaseDatosJSON:
    def __init__(self, archivo):
        self.archivo = archivo
        self._inicializar()

    def _inicializar(self):
        if not os.path.exists(self.archivo):
            self._guardar([])

    def _cargar(self):
        with open(self.archivo, "r", encoding="utf-8") as f:
            return json.load(f)

    def _guardar(self, datos):
        with open(self.archivo, "w", encoding="utf-8") as f:
            json.dump(datos, f, indent=2, ensure_ascii=False)

    def insertar(self, registro):
        datos = self._cargar()
        registro["id"] = len(datos) + 1
        datos.append(registro)
        self._guardar(datos)
        return registro["id"]

    def buscar(self, **criterios):
        datos = self._cargar()
        resultados = []
        for registro in datos:
            if all(registro.get(k) == v for k, v in criterios.items()):
                resultados.append(registro)
        return resultados

    def actualizar(self, id, **campos):
        datos = self._cargar()
        for registro in datos:
            if registro.get("id") == id:
                registro.update(campos)
                self._guardar(datos)
                return True
        return False

    def eliminar(self, id):
        datos = self._cargar()
        datos = [r for r in datos if r.get("id") != id]
        self._guardar(datos)

    def todos(self):
        return self._cargar()

# Uso
db = BaseDatosJSON("usuarios.json")

# Insertar
db.insertar({"nombre": "Ana", "email": "ana@email.com", "edad": 25})
db.insertar({"nombre": "Luis", "email": "luis@email.com", "edad": 30})
db.insertar({"nombre": "María", "email": "maria@email.com", "edad": 25})

# Buscar
print("Usuarios de 25 años:", db.buscar(edad=25))

# Actualizar
db.actualizar(1, edad=26)

# Ver todos
print("Todos los usuarios:", db.todos())

8.6. Manejo de Rutas

Módulo os.path

import os

# Obtener directorio actual
print(os.getcwd())

# Construir rutas
ruta = os.path.join("carpeta", "subcarpeta", "archivo.txt")
print(ruta)  # carpeta\subcarpeta\archivo.txt (Windows)

# Obtener partes de la ruta
ruta = "/home/usuario/documentos/archivo.txt"
print(os.path.basename(ruta))  # archivo.txt
print(os.path.dirname(ruta))   # /home/usuario/documentos
print(os.path.splitext(ruta))  # ('/home/.../archivo', '.txt')

# Verificar existencia
print(os.path.exists("archivo.txt"))
print(os.path.isfile("archivo.txt"))
print(os.path.isdir("carpeta"))

# Ruta absoluta
print(os.path.abspath("archivo.txt"))

Módulo pathlib (Moderno)

from pathlib import Path

# Crear objeto Path
ruta = Path("documentos/archivo.txt")

# Propiedades
print(ruta.name)        # archivo.txt
print(ruta.stem)        # archivo
print(ruta.suffix)      # .txt
print(ruta.parent)      # documentos
print(ruta.parts)       # ('documentos', 'archivo.txt')

# Verificar
print(ruta.exists())
print(ruta.is_file())
print(ruta.is_dir())

# Construir rutas
nueva_ruta = Path("carpeta") / "subcarpeta" / "archivo.txt"
print(nueva_ruta)

# Listar archivos
carpeta = Path(".")
for archivo in carpeta.iterdir():
    print(archivo)

# Buscar archivos por patrón
for py_file in Path(".").glob("*.py"):
    print(py_file)

# Buscar recursivamente
for txt_file in Path(".").rglob("*.txt"):
    print(txt_file)

# Crear directorios
Path("nueva_carpeta/subcarpeta").mkdir(parents=True, exist_ok=True)

# Leer/escribir directamente
archivo = Path("archivo.txt")
archivo.write_text("Hola mundo", encoding="utf-8")
contenido = archivo.read_text(encoding="utf-8")

8.7. Operaciones con Archivos

Copiar, Mover, Eliminar

import shutil
import os

# Copiar archivo
shutil.copy("origen.txt", "destino.txt")
shutil.copy2("origen.txt", "destino.txt")  # Preserva metadata

# Copiar directorio
shutil.copytree("carpeta_origen", "carpeta_destino")

# Mover archivo/directorio
shutil.move("archivo.txt", "nueva_ubicacion/archivo.txt")

# Eliminar archivo
os.remove("archivo.txt")

# Eliminar directorio vacío
os.rmdir("carpeta_vacia")

# Eliminar directorio con contenido
shutil.rmtree("carpeta_con_archivos")

Renombrar

import os

# Renombrar archivo
os.rename("nombre_viejo.txt", "nombre_nuevo.txt")

# Renombrar múltiples archivos
for archivo in os.listdir("."):
    if archivo.endswith(".txt"):
        nuevo_nombre = archivo.replace(".txt", "_backup.txt")
        os.rename(archivo, nuevo_nombre)

8.8. Archivos Binarios

Para imágenes, audio, ejecutables, etc.

# Leer archivo binario
with open("imagen.png", "rb") as f:
    datos = f.read()
    print(f"Tamaño: {len(datos)} bytes")

# Escribir archivo binario
with open("copia.png", "wb") as f:
    f.write(datos)

# Copiar archivo binario
with open("original.pdf", "rb") as origen:
    with open("copia.pdf", "wb") as destino:
        destino.write(origen.read())

8.9. Ejercicios Prácticos

Ejercicio 1: Análisis de Texto

def analizar_archivo(ruta):
    """Analiza un archivo de texto."""
    try:
        with open(ruta, "r", encoding="utf-8") as f:
            contenido = f.read()
    except FileNotFoundError:
        return "Error: Archivo no encontrado"
    except Exception as e:
        return f"Error: {e}"

    lineas = contenido.split("\n")
    palabras = contenido.split()
    caracteres = len(contenido)
    caracteres_sin_espacios = len(contenido.replace(" ", "").replace("\n", ""))

    # Palabra más frecuente
    frecuencias = {}
    for palabra in palabras:
        palabra = palabra.lower().strip(".,;:!?\"'")
        if palabra:
            frecuencias[palabra] = frecuencias.get(palabra, 0) + 1

    palabra_mas_comun = max(frecuencias.items(), key=lambda x: x[1]) if frecuencias else None

    return {
        "lineas": len(lineas),
        "palabras": len(palabras),
        "caracteres": caracteres,
        "caracteres_sin_espacios": caracteres_sin_espacios,
        "palabra_mas_comun": palabra_mas_comun
    }

# Uso
resultado = analizar_archivo("texto.txt")
for clave, valor in resultado.items():
    print(f"{clave}: {valor}")

Ejercicio 2: Procesador de Notas CSV

import csv

def procesar_notas(archivo_entrada, archivo_salida):
    """Procesa notas de estudiantes y genera informe."""
    estudiantes = []

    # Leer datos
    with open(archivo_entrada, "r", encoding="utf-8") as f:
        lector = csv.DictReader(f)
        for fila in lector:
            nombre = fila["nombre"]
            notas = [float(fila[k]) for k in fila if k.startswith("nota")]
            media = sum(notas) / len(notas)
            aprobado = media >= 5
            estudiantes.append({
                "nombre": nombre,
                "notas": notas,
                "media": round(media, 2),
                "aprobado": aprobado
            })

    # Escribir informe
    with open(archivo_salida, "w", encoding="utf-8") as f:
        f.write("INFORME DE CALIFICACIONES\n")
        f.write("=" * 40 + "\n\n")

        for e in estudiantes:
            estado = "APROBADO" if e["aprobado"] else "SUSPENSO"
            f.write(f"Estudiante: {e['nombre']}\n")
            f.write(f"  Notas: {e['notas']}\n")
            f.write(f"  Media: {e['media']}\n")
            f.write(f"  Estado: {estado}\n\n")

        # Estadísticas
        medias = [e["media"] for e in estudiantes]
        aprobados = sum(1 for e in estudiantes if e["aprobado"])

        f.write("-" * 40 + "\n")
        f.write("ESTADÍSTICAS\n")
        f.write(f"  Total estudiantes: {len(estudiantes)}\n")
        f.write(f"  Aprobados: {aprobados}\n")
        f.write(f"  Suspensos: {len(estudiantes) - aprobados}\n")
        f.write(f"  Media general: {sum(medias)/len(medias):.2f}\n")

    print(f"Informe generado en {archivo_salida}")

# Crear CSV de ejemplo
with open("notas.csv", "w", newline="", encoding="utf-8") as f:
    escritor = csv.writer(f)
    escritor.writerow(["nombre", "nota1", "nota2", "nota3"])
    escritor.writerow(["Ana", 8, 7, 9])
    escritor.writerow(["Luis", 5, 4, 6])
    escritor.writerow(["María", 9, 10, 8])
    escritor.writerow(["Pedro", 3, 4, 2])

procesar_notas("notas.csv", "informe_notas.txt")

Ejercicio 3: Organizador de Archivos

import os
import shutil
from pathlib import Path

def organizar_por_extension(directorio):
    """Organiza archivos en carpetas por extensión."""

    carpetas = {
        "Imágenes": [".jpg", ".jpeg", ".png", ".gif", ".bmp", ".svg"],
        "Documentos": [".pdf", ".doc", ".docx", ".txt", ".xlsx", ".pptx"],
        "Audio": [".mp3", ".wav", ".flac", ".aac"],
        "Video": [".mp4", ".avi", ".mkv", ".mov"],
        "Código": [".py", ".js", ".html", ".css", ".java", ".cpp"],
        "Comprimidos": [".zip", ".rar", ".7z", ".tar", ".gz"]
    }

    path = Path(directorio)

    for archivo in path.iterdir():
        if archivo.is_file():
            extension = archivo.suffix.lower()

            # Encontrar carpeta destino
            destino = "Otros"
            for carpeta, extensiones in carpetas.items():
                if extension in extensiones:
                    destino = carpeta
                    break

            # Crear carpeta si no existe
            carpeta_destino = path / destino
            carpeta_destino.mkdir(exist_ok=True)

            # Mover archivo
            try:
                shutil.move(str(archivo), str(carpeta_destino / archivo.name))
                print(f"Movido: {archivo.name} -> {destino}/")
            except Exception as e:
                print(f"Error moviendo {archivo.name}: {e}")

# Uso (¡cuidado con el directorio que uses!)
# organizar_por_extension("./descargas")

8.10. Resumen

Operación Código
Abrir archivo with open("archivo.txt", "r") as f:
Leer todo contenido = f.read()
Leer líneas lineas = f.readlines()
Escribir f.write("texto")
Modo escritura "w" (sobrescribe), "a" (añade)
CSV lectura csv.reader(f) o csv.DictReader(f)
CSV escritura csv.writer(f) o csv.DictWriter(f)
JSON lectura json.load(f)
JSON escritura json.dump(datos, f)
Rutas modernas from pathlib import Path

📅 Fecha de creación: Enero 2026
✍️ Autor: Fran García