diff --git a/README.md b/README.md
index bb203ce..947b514 100644
--- a/README.md
+++ b/README.md
@@ -85,7 +85,7 @@ The project foundation and six complete educational sections are available, and
- [Comments versus Logging in Python](comments-and-documentation/05-comments-vs-logging/README.md)
- [PEP 8 and Readability in Python](comments-and-documentation/06-pep8-and-readability/README.md)
-Phases 1, 2, 3, 4, 5, and 6 are complete. Phase 7 now includes three reviewed chapters: exception handling; deliberate raising and custom exceptions; and [Opening Files Safely with `open()` and `with`](errors-files-and-modules/03-open-and-with/README.md), which introduces text-file modes, explicit encodings, reading, writing, appending, focused file errors, and context-managed cleanup. Phase 5: Functions contains nine reviewed chapters: [Defining and Calling Functions](functions/01-defining-and-calling-functions/README.md), [Parameters and Arguments](functions/02-parameters-and-arguments/README.md), [Return Values](functions/03-return-values/README.md), [Scope](functions/04-scope/README.md), [Type Hints](functions/05-type-hints/README.md), [Default Values](functions/06-default-values/README.md), [`*args` and `**kwargs`](functions/07-args-and-kwargs/README.md), [Functions Working Together](functions/08-functions-working-together/README.md), and [Data Flow Between Functions](functions/09-data-flow-between-functions/README.md). Together they establish function definition and calling, required input flow, returned results, local and global scope, typed interfaces, safe optional inputs, intentionally flexible positional and keyword argument collection, composition through helpers and coordinators, and explicit caller-to-parameter-to-return data flow including rebinding versus mutation. Phase 4 remains complete with eight reviewed Program Flow chapters, ending with [Choosing and Combining Program Flow](program-flow/08-choosing-and-combining-program-flow/README.md). Phase 3 contains six reviewed Collections chapters, ending with [Choosing the Right Collection](collections/06-choosing-the-right-collection/README.md). Phase 2 remains complete with four reviewed chapters, ending with [Numeric Built-ins](strings-and-numbers/04-numeric-builtins/README.md). See the [roadmap](docs/roadmap.en.md) or the [full learning path](docs/learning-path.en.md) for the current curriculum status and direct chapter links.
+Phases 1, 2, 3, 4, 5, and 6 are complete. Phase 7 now includes four reviewed chapters: exception handling; deliberate raising and custom exceptions; safe file handling with `open()` and `with`; and [Working with TXT, CSV, and JSON](errors-files-and-modules/04-txt-csv-and-json/README.md), which adds line-oriented text contracts, CSV parsing and writing, JSON serialization and deserialization, and the boundary between parsing and validation. Phase 5: Functions contains nine reviewed chapters: [Defining and Calling Functions](functions/01-defining-and-calling-functions/README.md), [Parameters and Arguments](functions/02-parameters-and-arguments/README.md), [Return Values](functions/03-return-values/README.md), [Scope](functions/04-scope/README.md), [Type Hints](functions/05-type-hints/README.md), [Default Values](functions/06-default-values/README.md), [`*args` and `**kwargs`](functions/07-args-and-kwargs/README.md), [Functions Working Together](functions/08-functions-working-together/README.md), and [Data Flow Between Functions](functions/09-data-flow-between-functions/README.md). Together they establish function definition and calling, required input flow, returned results, local and global scope, typed interfaces, safe optional inputs, intentionally flexible positional and keyword argument collection, composition through helpers and coordinators, and explicit caller-to-parameter-to-return data flow including rebinding versus mutation. Phase 4 remains complete with eight reviewed Program Flow chapters, ending with [Choosing and Combining Program Flow](program-flow/08-choosing-and-combining-program-flow/README.md). Phase 3 contains six reviewed Collections chapters, ending with [Choosing the Right Collection](collections/06-choosing-the-right-collection/README.md). Phase 2 remains complete with four reviewed chapters, ending with [Numeric Built-ins](strings-and-numbers/04-numeric-builtins/README.md). See the [roadmap](docs/roadmap.en.md) or the [full learning path](docs/learning-path.en.md) for the current curriculum status and direct chapter links.
## Visual identity
diff --git a/docs/learning-path.en.md b/docs/learning-path.en.md
index b3913ad..fe4ecc9 100644
--- a/docs/learning-path.en.md
+++ b/docs/learning-path.en.md
@@ -94,8 +94,9 @@ This phase is already available and is the next recommended phase after Function
1. [Handling Exceptions with `try`, `except`, `else`, and `finally`](../errors-files-and-modules/01-try-except-else-finally/README.md)
2. [Raising and Custom Exceptions](../errors-files-and-modules/02-raise-and-custom-exceptions/README.md)
3. [Opening Files Safely with `open()` and `with`](../errors-files-and-modules/03-open-and-with/README.md)
+4. [Working with TXT, CSV, and JSON](../errors-files-and-modules/04-txt-csv-and-json/README.md)
-Phase 7 is in progress. Chapters 01–02 establish exception handling and deliberate signaling. Chapter 03 adds text-file modes, explicit encodings, reading, writing, appending, file exceptions, and context-managed cleanup. The next planned chapter is **TXT, CSV, and JSON**.
+Phase 7 is in progress. Chapters 01–02 establish exception handling and deliberate signaling. Chapter 03 adds safe file lifetime and text I/O. Chapter 04 adds TXT contracts, CSV parsing and writing, JSON serialization and deserialization, and explicit parsing-versus-validation boundaries. The next planned chapter is **Imports, Modules, and Packages**.
## Phase 8 · Standard Library ⏳
diff --git a/docs/learning-path.es.md b/docs/learning-path.es.md
index b6bb74e..aa6ba87 100644
--- a/docs/learning-path.es.md
+++ b/docs/learning-path.es.md
@@ -94,8 +94,9 @@ Esta fase ya está disponible y es la siguiente fase recomendada después de Fun
1. [Manejo de Excepciones con `try`, `except`, `else` y `finally`](../errors-files-and-modules/01-try-except-else-finally/README.es.md)
2. [Lanzar Excepciones y Crear Excepciones Personalizadas](../errors-files-and-modules/02-raise-and-custom-exceptions/README.es.md)
3. [Abrir Archivos de Forma Segura con `open()` y `with`](../errors-files-and-modules/03-open-and-with/README.es.md)
+4. [Trabajar con TXT, CSV y JSON](../errors-files-and-modules/04-txt-csv-and-json/README.es.md)
-La Fase 7 está en progreso. Los Capítulos 01–02 establecen manejo y señalización deliberada de excepciones. El Capítulo 03 añade modos de archivo de texto, encoding explícito, lectura, escritura, append, excepciones de archivo y limpieza gestionada por contexto. El próximo capítulo planificado es **TXT, CSV y JSON**.
+La Fase 7 está en progreso. Los Capítulos 01–02 establecen manejo y señalización deliberada de excepciones. El Capítulo 03 añade un tiempo de vida seguro de archivos e I/O de texto. El Capítulo 04 añade contratos TXT, parsing y escritura de CSV, serialización y deserialización JSON y límites explícitos entre parsing y validación. El próximo capítulo planificado es **Imports, Módulos y Paquetes**.
## Fase 8 · Biblioteca Estándar ⏳
diff --git a/docs/learning-path.pt-BR.md b/docs/learning-path.pt-BR.md
index f8f1cf4..e123a6a 100644
--- a/docs/learning-path.pt-BR.md
+++ b/docs/learning-path.pt-BR.md
@@ -94,8 +94,9 @@ Esta fase já está disponível e é a próxima fase recomendada depois de Funç
1. [Tratando Exceções com `try`, `except`, `else` e `finally`](../errors-files-and-modules/01-try-except-else-finally/README.pt-BR.md)
2. [Levantando Exceções e Criando Exceções Personalizadas](../errors-files-and-modules/02-raise-and-custom-exceptions/README.pt-BR.md)
3. [Abrindo Arquivos com Segurança com `open()` e `with`](../errors-files-and-modules/03-open-and-with/README.pt-BR.md)
+4. [Trabalhando com TXT, CSV e JSON](../errors-files-and-modules/04-txt-csv-and-json/README.pt-BR.md)
-A Fase 7 está em andamento. Os Capítulos 01–02 estabelecem tratamento e sinalização deliberada de exceções. O Capítulo 03 acrescenta modos de arquivo de texto, encoding explícito, leitura, escrita, append, exceções de arquivo e limpeza gerenciada por contexto. O próximo capítulo planejado é **TXT, CSV e JSON**.
+A Fase 7 está em andamento. Os Capítulos 01–02 estabelecem tratamento e sinalização deliberada de exceções. O Capítulo 03 acrescenta tempo de vida seguro de arquivos e I/O de texto. O Capítulo 04 adiciona contratos TXT, parsing e escrita de CSV, serialização e desserialização JSON e fronteiras explícitas entre parsing e validação. O próximo capítulo planejado é **Imports, Módulos e Pacotes**.
## Fase 8 · Biblioteca Padrão ⏳
diff --git a/docs/localized/README.es.md b/docs/localized/README.es.md
index 226646c..1651bc0 100644
--- a/docs/localized/README.es.md
+++ b/docs/localized/README.es.md
@@ -85,7 +85,7 @@ La base del proyecto y seis secciones educativas completas están disponibles, y
- [Comentarios frente a Logging en Python](../../comments-and-documentation/05-comments-vs-logging/README.es.md)
- [PEP 8 y Legibilidad en Python](../../comments-and-documentation/06-pep8-and-readability/README.es.md)
-Las Fases 1, 2, 3, 4, 5 y 6 están completadas. La Fase 7 ahora incluye tres capítulos revisados: manejo de excepciones; lanzamiento y excepciones personalizadas; y [Abrir Archivos de Forma Segura con `open()` y `with`](../../errors-files-and-modules/03-open-and-with/README.es.md), que introduce modos de archivo de texto, encoding explícito, lectura, escritura, append, errores de archivo específicos y limpieza gestionada por contexto. La Fase 5: Funciones reúne nueve capítulos revisados: [Definir y Llamar Funciones](../../functions/01-defining-and-calling-functions/README.es.md), [Parámetros y Argumentos](../../functions/02-parameters-and-arguments/README.es.md), [Valores de Retorno](../../functions/03-return-values/README.es.md), [Alcance](../../functions/04-scope/README.es.md), [Type Hints](../../functions/05-type-hints/README.es.md), [Valores Predeterminados](../../functions/06-default-values/README.es.md), [`*args` y `**kwargs`](../../functions/07-args-and-kwargs/README.es.md), [Funciones Trabajando Juntas](../../functions/08-functions-working-together/README.es.md) y [Flujo de Datos Entre Funciones](../../functions/09-data-flow-between-functions/README.es.md). Juntos establecen definición y llamada, flujo de entrada obligatorio, resultados retornados, alcance local y global, interfaces tipadas, entradas opcionales seguras, recolección intencionalmente flexible de argumentos posicionales y por palabra clave, composición mediante funciones auxiliares y coordinadoras y flujo explícito desde el llamador hacia parámetros y retornos, incluida la reasignación frente a la mutación. La Fase 4 permanece completada con ocho capítulos revisados de Flujo del Programa, terminando con [Elegir y Combinar el Flujo del Programa](../../program-flow/08-choosing-and-combining-program-flow/README.es.md). La Fase 3 reúne seis capítulos revisados de Colecciones, terminando con [Elegir la Colección Adecuada](../../collections/06-choosing-the-right-collection/README.es.md). La Fase 2 permanece completada con cuatro capítulos revisados, terminando con [Funciones Numéricas Incorporadas](../../strings-and-numbers/04-numeric-builtins/README.es.md). Consulta el [roadmap](../roadmap.es.md) o la [ruta completa de aprendizaje](../learning-path.es.md) para seguir el estado del currículo y acceder directamente a los capítulos.
+Las Fases 1, 2, 3, 4, 5 y 6 están completadas. La Fase 7 ahora incluye cuatro capítulos revisados: manejo de excepciones; lanzamiento y excepciones personalizadas; uso seguro de archivos con `open()` y `with`; y [Trabajar con TXT, CSV y JSON](../../errors-files-and-modules/04-txt-csv-and-json/README.es.md), que añade contratos de texto orientados a líneas, parsing y escritura de CSV, serialización y deserialización JSON y el límite entre parsing y validación. La Fase 5: Funciones reúne nueve capítulos revisados: [Definir y Llamar Funciones](../../functions/01-defining-and-calling-functions/README.es.md), [Parámetros y Argumentos](../../functions/02-parameters-and-arguments/README.es.md), [Valores de Retorno](../../functions/03-return-values/README.es.md), [Alcance](../../functions/04-scope/README.es.md), [Type Hints](../../functions/05-type-hints/README.es.md), [Valores Predeterminados](../../functions/06-default-values/README.es.md), [`*args` y `**kwargs`](../../functions/07-args-and-kwargs/README.es.md), [Funciones Trabajando Juntas](../../functions/08-functions-working-together/README.es.md) y [Flujo de Datos Entre Funciones](../../functions/09-data-flow-between-functions/README.es.md). Juntos establecen definición y llamada, flujo de entrada obligatorio, resultados retornados, alcance local y global, interfaces tipadas, entradas opcionales seguras, recolección intencionalmente flexible de argumentos posicionales y por palabra clave, composición mediante funciones auxiliares y coordinadoras y flujo explícito desde el llamador hacia parámetros y retornos, incluida la reasignación frente a la mutación. La Fase 4 permanece completada con ocho capítulos revisados de Flujo del Programa, terminando con [Elegir y Combinar el Flujo del Programa](../../program-flow/08-choosing-and-combining-program-flow/README.es.md). La Fase 3 reúne seis capítulos revisados de Colecciones, terminando con [Elegir la Colección Adecuada](../../collections/06-choosing-the-right-collection/README.es.md). La Fase 2 permanece completada con cuatro capítulos revisados, terminando con [Funciones Numéricas Incorporadas](../../strings-and-numbers/04-numeric-builtins/README.es.md). Consulta el [roadmap](../roadmap.es.md) o la [ruta completa de aprendizaje](../learning-path.es.md) para seguir el estado del currículo y acceder directamente a los capítulos.
## Identidad visual
diff --git a/docs/localized/README.pt-BR.md b/docs/localized/README.pt-BR.md
index 5f1e4f6..ae52de1 100644
--- a/docs/localized/README.pt-BR.md
+++ b/docs/localized/README.pt-BR.md
@@ -85,7 +85,7 @@ A fundação do projeto e seis seções educacionais completas estão disponíve
- [Comentários versus Logging em Python](../../comments-and-documentation/05-comments-vs-logging/README.pt-BR.md)
- [PEP 8 e Legibilidade em Python](../../comments-and-documentation/06-pep8-and-readability/README.pt-BR.md)
-As Fases 1, 2, 3, 4, 5 e 6 estão concluídas. A Fase 7 agora inclui três capítulos revisados: tratamento de exceções; levantamento e exceções personalizadas; e [Abrindo Arquivos com Segurança com `open()` e `with`](../../errors-files-and-modules/03-open-and-with/README.pt-BR.md), que introduz modos de arquivo de texto, encoding explícito, leitura, escrita, append, erros de arquivo específicos e limpeza gerenciada por contexto. A Fase 5: Funções reúne nove capítulos revisados: [Definindo e Chamando Funções](../../functions/01-defining-and-calling-functions/README.pt-BR.md), [Parâmetros e Argumentos](../../functions/02-parameters-and-arguments/README.pt-BR.md), [Valores de Retorno](../../functions/03-return-values/README.pt-BR.md), [Escopo](../../functions/04-scope/README.pt-BR.md), [Type Hints](../../functions/05-type-hints/README.pt-BR.md), [Valores Padrão](../../functions/06-default-values/README.pt-BR.md), [`*args` e `**kwargs`](../../functions/07-args-and-kwargs/README.pt-BR.md), [Funções Trabalhando Juntas](../../functions/08-functions-working-together/README.pt-BR.md) e [Fluxo de Dados Entre Funções](../../functions/09-data-flow-between-functions/README.pt-BR.md). Juntos, eles estabelecem definição e chamada, fluxo de entrada obrigatório, resultados retornados, escopo local e global, interfaces tipadas, entradas opcionais seguras, coleta intencionalmente flexível de argumentos posicionais e nomeados, composição por funções auxiliares e coordenadoras e fluxo explícito do chamador aos parâmetros e retornos, incluindo reatribuição versus mutação. A Fase 4 permanece concluída com oito capítulos revisados de Fluxo do Programa, encerrando com [Escolhendo e Combinando o Fluxo do Programa](../../program-flow/08-choosing-and-combining-program-flow/README.pt-BR.md). A Fase 3 reúne seis capítulos revisados de Coleções, encerrando com [Escolhendo a Coleção Certa](../../collections/06-choosing-the-right-collection/README.pt-BR.md). A Fase 2 permanece concluída com quatro capítulos revisados, encerrando com [Funções Numéricas Embutidas](../../strings-and-numbers/04-numeric-builtins/README.pt-BR.md). Consulte o [roadmap](../roadmap.pt-BR.md) ou a [trilha completa de estudos](../learning-path.pt-BR.md) para acompanhar o status do currículo e acessar os capítulos diretamente.
+As Fases 1, 2, 3, 4, 5 e 6 estão concluídas. A Fase 7 agora inclui quatro capítulos revisados: tratamento de exceções; levantamento e exceções personalizadas; uso seguro de arquivos com `open()` e `with`; e [Trabalhando com TXT, CSV e JSON](../../errors-files-and-modules/04-txt-csv-and-json/README.pt-BR.md), que acrescenta contratos de texto orientados por linhas, parsing e escrita de CSV, serialização e desserialização JSON e a fronteira entre parsing e validação. A Fase 5: Funções reúne nove capítulos revisados: [Definindo e Chamando Funções](../../functions/01-defining-and-calling-functions/README.pt-BR.md), [Parâmetros e Argumentos](../../functions/02-parameters-and-arguments/README.pt-BR.md), [Valores de Retorno](../../functions/03-return-values/README.pt-BR.md), [Escopo](../../functions/04-scope/README.pt-BR.md), [Type Hints](../../functions/05-type-hints/README.pt-BR.md), [Valores Padrão](../../functions/06-default-values/README.pt-BR.md), [`*args` e `**kwargs`](../../functions/07-args-and-kwargs/README.pt-BR.md), [Funções Trabalhando Juntas](../../functions/08-functions-working-together/README.pt-BR.md) e [Fluxo de Dados Entre Funções](../../functions/09-data-flow-between-functions/README.pt-BR.md). Juntos, eles estabelecem definição e chamada, fluxo de entrada obrigatório, resultados retornados, escopo local e global, interfaces tipadas, entradas opcionais seguras, coleta intencionalmente flexível de argumentos posicionais e nomeados, composição por funções auxiliares e coordenadoras e fluxo explícito do chamador aos parâmetros e retornos, incluindo reatribuição versus mutação. A Fase 4 permanece concluída com oito capítulos revisados de Fluxo do Programa, encerrando com [Escolhendo e Combinando o Fluxo do Programa](../../program-flow/08-choosing-and-combining-program-flow/README.pt-BR.md). A Fase 3 reúne seis capítulos revisados de Coleções, encerrando com [Escolhendo a Coleção Certa](../../collections/06-choosing-the-right-collection/README.pt-BR.md). A Fase 2 permanece concluída com quatro capítulos revisados, encerrando com [Funções Numéricas Embutidas](../../strings-and-numbers/04-numeric-builtins/README.pt-BR.md). Consulte o [roadmap](../roadmap.pt-BR.md) ou a [trilha completa de estudos](../learning-path.pt-BR.md) para acompanhar o status do currículo e acessar os capítulos diretamente.
## Identidade visual
diff --git a/docs/project-structure.en.md b/docs/project-structure.en.md
index 41c14b3..1378d93 100644
--- a/docs/project-structure.en.md
+++ b/docs/project-structure.en.md
@@ -157,14 +157,23 @@ python-study-guide/
│ │ ├── custom_exception.py
│ │ ├── exception_chaining.py
│ │ └── validate_score.py
-│ └── 03-open-and-with/
+│ ├── 03-open-and-with/
+│ │ ├── README.md
+│ │ ├── README.pt-BR.md
+│ │ ├── README.es.md
+│ │ └── examples/
+│ │ ├── append_text.py
+│ │ ├── handle_missing_file.py
+│ │ └── write_and_read_text.py
+│ └── 04-txt-csv-and-json/
│ ├── README.md
│ ├── README.pt-BR.md
│ ├── README.es.md
│ └── examples/
-│ ├── append_text.py
-│ ├── handle_missing_file.py
-│ └── write_and_read_text.py
+│ ├── csv_records.py
+│ ├── handle_invalid_json.py
+│ ├── json_document.py
+│ └── text_records.py
├── exercises/
├── external-libraries/
├── functions/
@@ -416,7 +425,7 @@ python-study-guide/
- `comments-and-documentation/`: complete Phase 6 learning path. Reviewed chapters are available for comments, docstrings, meaningful names, task markers, comments versus logging, and PEP 8 and readability, each in English, Brazilian Portuguese, and Spanish with safe executable examples.
- `collections/`: complete Phase 3 learning path. Its six chapters teach list creation, reading, mutation, common methods, shallow copying, tuples and immutability, dictionary key-value mappings and views, set uniqueness and relationships, and how to choose among lists, tuples, dictionaries, and sets by intent, in English, Brazilian Portuguese, and Spanish with safe executable examples.
- `docs/`: master learning paths, roadmaps, project architecture, localized project documents, policies, and responsible AI-assisted development guidance.
-- `errors-files-and-modules/`: in-progress Phase 7 learning path. Chapters 01–03 cover runtime exception handling, deliberate raising and custom exceptions, and safe text-file I/O with `open()`, explicit encodings, file modes, focused file exceptions, and `with`, in English, Brazilian Portuguese, and Spanish with deterministic executable examples.
+- `errors-files-and-modules/`: in-progress Phase 7 learning path. Chapters 01–04 cover runtime exception handling, deliberate raising and custom exceptions, safe text-file I/O with `open()` and `with`, and TXT/CSV/JSON parsing, writing, conversion, and validation boundaries, in English, Brazilian Portuguese, and Spanish with deterministic executable examples.
- `exercises/`: focused practice activities connected to learning chapters.
- `external-libraries/`: future guides to third-party packages.
- `functions/`: complete Phase 5 learning path. Chapters 01–09 cover defining and calling functions, required inputs, returned values, scope and name lookup, type hints for function interfaces, default values including definition-time evaluation and mutable-default safety, variable-length positional and keyword argument collection with `*args` and `**kwargs`, composition through helper and coordinating functions with explicit dependencies and simple call graphs, and explicit data-flow tracing across calls including parameter bindings, rebinding versus mutation, `None`, tuple results, and return-based handoffs, in English, Brazilian Portuguese, and Spanish with deterministic executable examples.
@@ -445,4 +454,4 @@ English uses canonical root files recognized automatically by GitHub. Brazilian
## Maintenance rule
-A pull request that moves, creates, or removes significant paths must update this structure in the same change. New executable examples must also be reviewed for unattended execution and registered in `scripts/example_manifest.txt` when approved for CI.
\ No newline at end of file
+A pull request that moves, creates, or removes significant paths must update this structure in the same change. New executable examples must also be reviewed for unattended execution and registered in `scripts/example_manifest.txt` when approved for CI.
diff --git a/docs/project-structure.es.md b/docs/project-structure.es.md
index 924f577..5589ca7 100644
--- a/docs/project-structure.es.md
+++ b/docs/project-structure.es.md
@@ -157,14 +157,23 @@ python-study-guide/
│ │ ├── custom_exception.py
│ │ ├── exception_chaining.py
│ │ └── validate_score.py
-│ └── 03-open-and-with/
+│ ├── 03-open-and-with/
+│ │ ├── README.md
+│ │ ├── README.pt-BR.md
+│ │ ├── README.es.md
+│ │ └── examples/
+│ │ ├── append_text.py
+│ │ ├── handle_missing_file.py
+│ │ └── write_and_read_text.py
+│ └── 04-txt-csv-and-json/
│ ├── README.md
│ ├── README.pt-BR.md
│ ├── README.es.md
│ └── examples/
-│ ├── append_text.py
-│ ├── handle_missing_file.py
-│ └── write_and_read_text.py
+│ ├── csv_records.py
+│ ├── handle_invalid_json.py
+│ ├── json_document.py
+│ └── text_records.py
├── exercises/
├── external-libraries/
├── functions/
@@ -416,7 +425,7 @@ python-study-guide/
- `comments-and-documentation/`: ruta completa de la Fase 6. Hay capítulos revisados sobre comentarios, docstrings, nombres significativos, marcadores de tareas, comentarios frente a logging y PEP 8 y legibilidad, cada uno en inglés, portugués de Brasil y español, con ejemplos ejecutables seguros.
- `collections/`: ruta completa de la Fase 3. Sus seis capítulos enseñan creación, lectura, mutación y métodos comunes de listas, copia superficial, tuplas e inmutabilidad, mappings clave-valor y vistas de diccionarios, unicidad y relaciones de conjuntos y cómo elegir entre listas, tuplas, diccionarios y conjuntos según la intención, en inglés, portugués de Brasil y español, con ejemplos ejecutables seguros.
- `docs/`: rutas completas de aprendizaje, roadmaps, arquitectura del proyecto, documentos localizados, políticas y guía de desarrollo responsable asistido por IA.
-- `errors-files-and-modules/`: ruta en progreso de la Fase 7. Los Capítulos 01–03 cubren manejo de excepciones de runtime, lanzamiento y excepciones personalizadas e I/O seguro de archivos de texto con `open()`, encoding explícito, modos de archivo, excepciones de archivo específicas y `with`, en inglés, portugués de Brasil y español con ejemplos ejecutables determinísticos.
+- `errors-files-and-modules/`: ruta de la Fase 7 en progreso. Los Capítulos 01–04 cubren manejo de excepciones en runtime, lanzamiento deliberado y excepciones personalizadas, I/O seguro de archivos de texto con `open()` y `with` y parsing, escritura, conversión y límites de validación para TXT/CSV/JSON, en inglés, portugués de Brasil y español con ejemplos ejecutables deterministas.
- `exercises/`: actividades prácticas relacionadas con los capítulos.
- `external-libraries/`: futuras guías sobre paquetes de terceros.
- `functions/`: ruta completa de la Fase 5. Los Capítulos 01–09 cubren definición y llamada de funciones, entradas obligatorias, valores retornados, alcance y búsqueda de nombres, type hints para interfaces de funciones, valores predeterminados incluida la evaluación al definir la función y la seguridad con valores mutables, recolección de argumentos posicionales y por palabra clave de cantidad variable con `*args` y `**kwargs`, composición mediante funciones auxiliares y coordinadoras con dependencias explícitas y grafos simples de llamadas, y seguimiento explícito del flujo de datos entre llamadas, incluidos vínculos de parámetros, reasignación frente a mutación, `None`, resultados en tupla y traspasos mediante `return`, en inglés, portugués de Brasil y español, con ejemplos ejecutables determinísticos.
@@ -445,4 +454,4 @@ El inglés utiliza archivos canónicos reconocidos automáticamente por GitHub.
## Regla de mantenimiento
-Un pull request que mueva, cree o elimine rutas importantes debe actualizar esta estructura en el mismo cambio. Los nuevos ejemplos ejecutables también deben revisarse para ejecución automática y registrarse en `scripts/example_manifest.txt` cuando se aprueben para CI.
\ No newline at end of file
+Un pull request que mueva, cree o elimine rutas importantes debe actualizar esta estructura en el mismo cambio. Los nuevos ejemplos ejecutables también deben revisarse para ejecución automática y registrarse en `scripts/example_manifest.txt` cuando se aprueben para CI.
diff --git a/docs/project-structure.pt-BR.md b/docs/project-structure.pt-BR.md
index 272aaf3..2c96e7f 100644
--- a/docs/project-structure.pt-BR.md
+++ b/docs/project-structure.pt-BR.md
@@ -157,14 +157,23 @@ python-study-guide/
│ │ ├── custom_exception.py
│ │ ├── exception_chaining.py
│ │ └── validate_score.py
-│ └── 03-open-and-with/
+│ ├── 03-open-and-with/
+│ │ ├── README.md
+│ │ ├── README.pt-BR.md
+│ │ ├── README.es.md
+│ │ └── examples/
+│ │ ├── append_text.py
+│ │ ├── handle_missing_file.py
+│ │ └── write_and_read_text.py
+│ └── 04-txt-csv-and-json/
│ ├── README.md
│ ├── README.pt-BR.md
│ ├── README.es.md
│ └── examples/
-│ ├── append_text.py
-│ ├── handle_missing_file.py
-│ └── write_and_read_text.py
+│ ├── csv_records.py
+│ ├── handle_invalid_json.py
+│ ├── json_document.py
+│ └── text_records.py
├── exercises/
├── external-libraries/
├── functions/
@@ -416,7 +425,7 @@ python-study-guide/
- `comments-and-documentation/`: trilha completa da Fase 6. Há capítulos revisados sobre comentários, docstrings, nomes significativos, marcadores de tarefas, comentários versus logging e PEP 8 e legibilidade, cada um em inglês, português brasileiro e espanhol, com exemplos executáveis seguros.
- `collections/`: trilha completa da Fase 3. Seus seis capítulos ensinam criação, leitura, mutação e métodos comuns de listas, cópia rasa, tuplas e imutabilidade, mapeamentos chave-valor e views de dicionários, unicidade e relações de conjuntos e como escolher entre listas, tuplas, dicionários e conjuntos de acordo com a intenção, em inglês, português brasileiro e espanhol, com exemplos executáveis seguros.
- `docs/`: trilhas completas de estudos, roadmaps, arquitetura do projeto, documentos localizados, políticas e guia de desenvolvimento responsável assistido por IA.
-- `errors-files-and-modules/`: trilha em andamento da Fase 7. Os Capítulos 01–03 cobrem tratamento de exceções de runtime, levantamento e exceções personalizadas e I/O seguro de arquivos de texto com `open()`, encoding explícito, modos de arquivo, exceções de arquivo específicas e `with`, em inglês, português brasileiro e espanhol com exemplos executáveis determinísticos.
+- `errors-files-and-modules/`: trilha da Fase 7 em andamento. Os Capítulos 01–04 cobrem tratamento de exceções em runtime, levantamento deliberado e exceções personalizadas, I/O seguro de arquivos de texto com `open()` e `with` e parsing, escrita, conversão e fronteiras de validação para TXT/CSV/JSON, em inglês, português brasileiro e espanhol com exemplos executáveis determinísticos.
- `exercises/`: atividades práticas relacionadas aos capítulos.
- `external-libraries/`: futuros guias sobre pacotes de terceiros.
- `functions/`: trilha completa da Fase 5. Os Capítulos 01–09 cobrem definição e chamada de funções, entradas obrigatórias, valores retornados, escopo e busca de nomes, type hints para interfaces de funções, valores padrão incluindo avaliação no momento da definição e segurança com padrões mutáveis, coleta de argumentos posicionais e nomeados de quantidade variável com `*args` e `**kwargs`, composição por funções auxiliares e coordenadoras com dependências explícitas e grafos simples de chamadas e rastreamento explícito do fluxo de dados entre chamadas, incluindo vínculos de parâmetros, reatribuição versus mutação, `None`, resultados em tupla e passagens por `return`, em inglês, português brasileiro e espanhol com exemplos executáveis determinísticos.
@@ -445,4 +454,4 @@ O inglês utiliza arquivos canônicos reconhecidos automaticamente pelo GitHub.
## Regra de manutenção
-Um pull request que mover, criar ou remover caminhos importantes deve atualizar esta estrutura na mesma alteração. Novos exemplos executáveis também devem ser revisados para execução automática e registrados em `scripts/example_manifest.txt` quando aprovados para o CI.
\ No newline at end of file
+Um pull request que mover, criar ou remover caminhos importantes deve atualizar esta estrutura na mesma alteração. Novos exemplos executáveis também devem ser revisados para execução automática e registrados em `scripts/example_manifest.txt` quando aprovados para o CI.
diff --git a/docs/roadmap.en.md b/docs/roadmap.en.md
index 19d7b92..e57c7cf 100644
--- a/docs/roadmap.en.md
+++ b/docs/roadmap.en.md
@@ -21,12 +21,12 @@ This roadmap tracks both the educational curriculum and the repository foundatio
| 4. Program flow | Complete | Eight reviewed chapters cover conditions, branching, structural pattern matching, `for`, iteration helpers, `while`, loop control, and choosing and combining flow tools by intent |
| 5. Functions | Complete | Nine reviewed chapters cover `def`, calls, required inputs, returned values, scope, type hints, safe defaults, flexible arguments, function composition, and explicit data flow |
| 6. Comments, documentation, and clean code | Complete | Six reviewed chapters are available and the pilot educational section is officially complete |
-| 7. Errors, files, and modules | In progress | Chapters 01–03 cover exception handling, deliberate exception signaling, and safe text-file I/O with `open()` and `with` |
+| 7. Errors, files, and modules | In progress | Chapters 01–04 cover exception handling, deliberate exception signaling, safe file I/O, and TXT/CSV/JSON data formats |
| 8. Standard library | Planned | Curriculum not started |
| 9. External libraries | Planned | Curriculum not started |
| 10. Practical projects | Planned | Curriculum not started |
-Phases 0, 1, 2, 3, 4, 5, and 6 are complete. Phase 7 is in progress with both exception handling and deliberate exception raising now available before the later file and module chapters. Phase 6 continues to provide the editorial and quality model for later sections.
+Phases 0, 1, 2, 3, 4, 5, and 6 are complete. Phase 7 is in progress with exception handling, deliberate exception signaling, safe file I/O, and TXT/CSV/JSON data-format boundaries now available. The final planned Phase 7 chapter is **Imports, modules, and packages**. Phase 6 continues to provide the editorial and quality model for later sections.
## Phase 0: Project foundation
@@ -131,10 +131,10 @@ See the [section learning path](../errors-files-and-modules/README.md).
- [x] [`try`, `except`, `else`, and `finally`](../errors-files-and-modules/01-try-except-else-finally/README.md)
- [x] [`raise` and custom exceptions](../errors-files-and-modules/02-raise-and-custom-exceptions/README.md)
- [x] [`open()` and `with`](../errors-files-and-modules/03-open-and-with/README.md)
-- [ ] TXT, CSV, and JSON
+- [x] [TXT, CSV, and JSON](../errors-files-and-modules/04-txt-csv-and-json/README.md)
- [ ] Imports, modules, and packages
-Phase 7 is in progress. Chapters 01–02 establish exception handling and deliberate signaling. Chapter 03 adds safe text-file I/O with modes, explicit encodings, reading, writing, appending, focused file exceptions, and `with`. The next planned chapter is **TXT, CSV, and JSON**.
+Phase 7 is in progress. Chapters 01–02 establish exception handling and deliberate signaling. Chapter 03 adds safe text-file I/O and resource lifetime. Chapter 04 adds TXT contracts, CSV and JSON parsing/writing, explicit type conversion, and parsing-versus-validation boundaries. The next planned chapter is **Imports, modules, and packages**.
## Phase 8: Standard library
@@ -190,4 +190,4 @@ Every phase should preserve:
- documentation of meaningful structure changes;
- honest dependency and version assumptions.
-The roadmap will evolve as the project grows, but changes should preserve the progression from beginner concepts to integrated practical work.
\ No newline at end of file
+The roadmap will evolve as the project grows, but changes should preserve the progression from beginner concepts to integrated practical work.
diff --git a/docs/roadmap.es.md b/docs/roadmap.es.md
index c67cb1f..71f84f1 100644
--- a/docs/roadmap.es.md
+++ b/docs/roadmap.es.md
@@ -21,12 +21,12 @@ Este roadmap acompaña tanto la ruta educativa como la base del repositorio que
| 4. Flujo del programa | Completada | Ocho capítulos revisados cubren condiciones, ramificaciones, coincidencia de patrones estructurales, `for`, ayudas de iteración, `while`, control de bucles y elección y combinación de herramientas de flujo según la intención |
| 5. Funciones | Completada | Nueve capítulos revisados cubren `def`, llamadas, entradas obligatorias, valores retornados, alcance, type hints, valores predeterminados seguros, argumentos flexibles, composición de funciones y flujo explícito de datos |
| 6. Comentarios, documentación y código limpio | Completada | Seis capítulos revisados están disponibles y la sección educativa piloto está oficialmente completada |
-| 7. Errores, archivos y módulos | En progreso | Los Capítulos 01–03 cubren manejo de excepciones, señalización deliberada e I/O seguro de archivos de texto con `open()` y `with` |
+| 7. Errores, archivos y módulos | En progreso | Los Capítulos 01–04 cubren manejo de excepciones, señalización deliberada, I/O seguro de archivos y formatos TXT/CSV/JSON |
| 8. Biblioteca estándar | Planificada | Contenido todavía no iniciado |
| 9. Bibliotecas externas | Planificada | Contenido todavía no iniciado |
| 10. Proyectos prácticos | Planificada | Contenido todavía no iniciado |
-Las Fases 0, 1, 2, 3, 4, 5 y 6 están completadas. La Fase 7 está en progreso, ahora con manejo y lanzamiento deliberado de excepciones disponibles antes de los capítulos posteriores sobre archivos y módulos. La Fase 6 continúa proporcionando el modelo editorial y de calidad para las secciones posteriores.
+Las Fases 0, 1, 2, 3, 4, 5 y 6 están completadas. La Fase 7 está en progreso con manejo de excepciones, señalización deliberada, I/O seguro de archivos y límites de formatos TXT/CSV/JSON ya disponibles. El último capítulo planificado de la Fase 7 es **Imports, módulos y paquetes**. La Fase 6 continúa proporcionando el modelo editorial y de calidad para las secciones posteriores.
## Fase 0: Base del proyecto
@@ -131,10 +131,10 @@ Consulta la [ruta de aprendizaje de la sección](../errors-files-and-modules/REA
- [x] [`try`, `except`, `else` y `finally`](../errors-files-and-modules/01-try-except-else-finally/README.es.md)
- [x] [`raise` y excepciones personalizadas](../errors-files-and-modules/02-raise-and-custom-exceptions/README.es.md)
- [x] [`open()` y `with`](../errors-files-and-modules/03-open-and-with/README.es.md)
-- [ ] TXT, CSV y JSON
+- [x] [TXT, CSV y JSON](../errors-files-and-modules/04-txt-csv-and-json/README.es.md)
- [ ] Imports, módulos y paquetes
-La Fase 7 está en progreso. Los Capítulos 01–02 establecen manejo y señalización deliberada de excepciones. El Capítulo 03 añade I/O seguro de archivos de texto con modos, encoding explícito, lectura, escritura, append, excepciones de archivo específicas y `with`. El próximo capítulo planificado es **TXT, CSV y JSON**.
+La Fase 7 está en progreso. Los Capítulos 01–02 establecen manejo y señalización deliberada de excepciones. El Capítulo 03 añade I/O seguro de archivos y gestión de recursos. El Capítulo 04 añade contratos TXT, parsing y escritura de CSV y JSON, conversión explícita de tipos y límites entre parsing y validación. El próximo capítulo planificado es **Imports, módulos y paquetes**.
## Fase 8: Biblioteca estándar
diff --git a/docs/roadmap.pt-BR.md b/docs/roadmap.pt-BR.md
index 4827989..65ab30e 100644
--- a/docs/roadmap.pt-BR.md
+++ b/docs/roadmap.pt-BR.md
@@ -21,12 +21,12 @@ Este roadmap acompanha tanto a trilha educacional quanto a fundação do reposit
| 4. Fluxo do programa | Concluída | Oito capítulos revisados cobrem condições, ramificações, correspondência de padrões estruturais, `for`, auxiliares de iteração, `while`, controle de loops e escolha e combinação das ferramentas de fluxo pela intenção |
| 5. Funções | Concluída | Nove capítulos revisados cobrem `def`, chamadas, entradas obrigatórias, valores retornados, escopo, type hints, valores padrão seguros, argumentos flexíveis, composição de funções e fluxo explícito de dados |
| 6. Comentários, documentação e código limpo | Concluída | Seis capítulos revisados estão disponíveis e a seção educacional-piloto está oficialmente concluída |
-| 7. Erros, arquivos e módulos | Em andamento | Os Capítulos 01–03 cobrem tratamento de exceções, sinalização deliberada e I/O seguro de arquivos de texto com `open()` e `with` |
+| 7. Erros, arquivos e módulos | Em andamento | Os Capítulos 01–04 cobrem tratamento de exceções, sinalização deliberada, I/O seguro de arquivos e formatos TXT/CSV/JSON |
| 8. Biblioteca padrão | Planejada | Conteúdo ainda não iniciado |
| 9. Bibliotecas externas | Planejada | Conteúdo ainda não iniciado |
| 10. Projetos práticos | Planejada | Conteúdo ainda não iniciado |
-As Fases 0, 1, 2, 3, 4, 5 e 6 estão concluídas. A Fase 7 está em andamento, agora com tratamento e levantamento deliberado de exceções disponíveis antes dos capítulos posteriores sobre arquivos e módulos. A Fase 6 continua fornecendo o modelo editorial e de qualidade para as seções posteriores.
+As Fases 0, 1, 2, 3, 4, 5 e 6 estão concluídas. A Fase 7 está em andamento com tratamento de exceções, sinalização deliberada, I/O seguro de arquivos e fronteiras de formatos TXT/CSV/JSON já disponíveis. O último capítulo planejado da Fase 7 é **Imports, módulos e pacotes**. A Fase 6 continua fornecendo o modelo editorial e de qualidade para as seções posteriores.
## Fase 0: Fundação do projeto
@@ -131,10 +131,10 @@ Consulte a [trilha de aprendizagem da seção](../errors-files-and-modules/READM
- [x] [`try`, `except`, `else` e `finally`](../errors-files-and-modules/01-try-except-else-finally/README.pt-BR.md)
- [x] [`raise` e exceções personalizadas](../errors-files-and-modules/02-raise-and-custom-exceptions/README.pt-BR.md)
- [x] [`open()` e `with`](../errors-files-and-modules/03-open-and-with/README.pt-BR.md)
-- [ ] TXT, CSV e JSON
+- [x] [TXT, CSV e JSON](../errors-files-and-modules/04-txt-csv-and-json/README.pt-BR.md)
- [ ] Imports, módulos e pacotes
-A Fase 7 está em andamento. Os Capítulos 01–02 estabelecem tratamento e sinalização deliberada de exceções. O Capítulo 03 acrescenta I/O seguro de arquivos de texto com modos, encoding explícito, leitura, escrita, append, exceções de arquivo específicas e `with`. O próximo capítulo planejado é **TXT, CSV e JSON**.
+A Fase 7 está em andamento. Os Capítulos 01–02 estabelecem tratamento e sinalização deliberada de exceções. O Capítulo 03 acrescenta I/O seguro de arquivos e gerenciamento de recursos. O Capítulo 04 acrescenta contratos TXT, parsing e escrita de CSV e JSON, conversão explícita de tipos e fronteiras entre parsing e validação. O próximo capítulo planejado é **Imports, módulos e pacotes**.
## Fase 8: Biblioteca padrão
diff --git a/errors-files-and-modules/04-txt-csv-and-json/README.es.md b/errors-files-and-modules/04-txt-csv-and-json/README.es.md
new file mode 100644
index 0000000..f2b3a27
--- /dev/null
+++ b/errors-files-and-modules/04-txt-csv-and-json/README.es.md
@@ -0,0 +1,887 @@
+
+
+# Trabajar con TXT, CSV y JSON
+
+[🇺🇸 English](README.md) · [🇧🇷 Português](README.pt-BR.md) · [🇪🇸 Español](README.es.md)
+
+
+
+[← Volver a Errores, Archivos y Módulos](../README.es.md) · [← Anterior: Abrir Archivos de Forma Segura con `open()` y `with`](../03-open-and-with/README.es.md)
+
+Abrir un archivo de forma segura es solo la mitad del trabajo. Un programa también necesita comprender **cómo están organizados los datos dentro de ese archivo**.
+
+Un archivo `.txt` puede contener un registro por línea, un CSV puede representar filas y columnas y un documento JSON puede representar objetos y arrays anidados. La extensión es una pista útil, pero el contrato real es el formato de los datos y las reglas usadas para interpretarlos.
+
+Este capítulo introduce registros de texto simple, el módulo `csv` de Python y el módulo `json` de Python. El objetivo no es memorizar todas las opciones. El objetivo es elegir un formato deliberadamente, usar el parser responsable de ese formato y mantener el parsing separado de la validación y la lógica de la aplicación.
+
+**Tiempo estimado de estudio:** 120–160 minutos.
+
+**Requisito de Python:** Python 3.10 o posterior. El comportamiento de `csv` y `json` enseñado aquí se verificó con la documentación oficial de Python 3.14.
+
+## Objetivos de aprendizaje
+
+Al final de este capítulo, deberías poder:
+
+- explicar la diferencia entre una extensión de archivo y un formato de datos;
+- usar texto simple cuando un contrato orientado a líneas sea suficiente;
+- explicar por qué CSV no debe analizarse con un `split(",")` ingenuo;
+- leer y escribir filas CSV con el módulo `csv` de la biblioteca estándar;
+- usar `DictReader` y `DictWriter` cuando las columnas con nombre mejoren la claridad;
+- explicar por qué los valores CSV normalmente llegan como strings y convertirlos deliberadamente;
+- abrir archivos CSV con `newline=""` y una codificación de texto conocida;
+- distinguir objetos, arrays, strings, números, booleanos y `null` en JSON;
+- usar correctamente `json.load()`, `json.loads()`, `json.dump()` y `json.dumps()`;
+- manejar JSON no válido con `json.JSONDecodeError` cuando exista una recuperación significativa;
+- distinguir parsing de validación;
+- elegir TXT, CSV o JSON según la forma y el contrato de los datos;
+- evitar parsers hechos a mano cuando ya existe un parser específico del formato.
+
+## 1. Un archivo es un contenedor; un formato es un contrato
+
+El Capítulo 03 se centró en abrir, leer, escribir y cerrar archivos. Este capítulo añade otra pregunta:
+
+```text
+bytes en almacenamiento
+ ↓ decodificación
+texto en Python
+ ↓ parsing
+valores Python estructurados
+ ↓ validación
+valores en los que el programa confía
+```
+
+Abrir un archivo responde **de dónde vienen los datos**. Hacer parsing responde **qué significa el texto**.
+
+Son responsabilidades relacionadas, pero no son la misma responsabilidad.
+
+## 2. La extensión no interpreta mágicamente el contenido
+
+Un nombre como `topics.txt`, `scores.csv` o `profile.json` comunica intención a personas y herramientas. Python no inspecciona automáticamente la extensión y transforma el contenido en la estructura correspondiente.
+
+Tú eliges la operación apropiada:
+
+```python
+with open("topics.txt", "r", encoding="utf-8") as file:
+ text = file.read()
+```
+
+o un parser específico del formato, como `csv.reader()` o `json.load()`.
+
+## 3. TXT significa texto, no un único esquema universal
+
+`.txt` normalmente significa texto simple, pero no existe un único formato universal de registros TXT.
+
+Todos estos podrían ser contratos válidos de archivo de texto:
+
+```text
+Functions
+Exceptions
+Files
+```
+
+```text
+topic=Functions
+level=2
+active=true
+```
+
+```text
+2026-08-26 | Files | completed
+```
+
+El programa y quien produce el archivo deben acordar las reglas.
+
+## 4. Un contrato TXT simple puede tener un registro por línea
+
+Si cada línea es un valor de texto independiente, el formato puede mantenerse intencionalmente simple:
+
+```python
+with open("topics.txt", "r", encoding="utf-8") as file:
+ topics = [line.rstrip("\n") for line in file]
+```
+
+Aquí el parser es pequeño porque el contrato es pequeño: cada línea física representa un tema.
+
+## 5. Conserva el espacio significativo de forma deliberada
+
+Evita usar `strip()` automáticamente cuando los espacios puedan pertenecer a los datos.
+
+```python
+clean_line = line.rstrip("\n")
+```
+
+Esto elimina solo el carácter de nueva línea definido por la decisión de formato anterior.
+
+Si tu formato define otras reglas de normalización, aplícalas explícitamente en lugar de tratar todo espacio en blanco como descartable.
+
+## 6. Los separadores personalizados simples siguen formando un formato que debe definirse
+
+Supón que un archivo controlado contiene un par clave-valor por línea:
+
+```text
+topic=Files
+level=2
+```
+
+Un parser deliberado puede dividir solo en el primer separador:
+
+```python
+key, value = line.rstrip("\n").split("=", 1)
+```
+
+El `1` importa si el propio valor puede contener `=` después.
+
+Cuando aparecen escape, comillas, columnas opcionales, datos anidados o muchos casos límite, un formato estándar suele ser mejor que hacer crecer un minilenguaje privado.
+
+## 7. CSV representa registros tabulares
+
+CSV es útil cuando los datos naturalmente parecen filas con las mismas columnas:
+
+```text
+topic,score,status
+Functions,91,complete
+Files,88,complete
+JSON,79,review
+```
+
+El nombre significa valores separados por comas, pero los datos CSV reales pueden usar delimitadores y reglas de comillas diferentes. Python modela esas elecciones mediante dialectos y opciones de formato CSV.
+
+## 8. No analices CSV con `split(",")`
+
+Esto parece tentador:
+
+```python
+columns = line.split(",")
+```
+
+pero un campo válido puede contener una coma cuando está entre comillas:
+
+```text
+topic,note
+Files,"Read, write, and validate"
+```
+
+Un parser CSV entiende delimitadores, comillas, nuevas líneas incrustadas y otras reglas del formato. Un simple split de string no.
+
+## 9. Importa el módulo `csv` de la biblioteca estándar
+
+El módulo forma parte de la biblioteca estándar de Python:
+
+```python
+import csv
+```
+
+Proporciona APIs orientadas a filas como:
+
+- `csv.reader()`;
+- `csv.writer()`;
+- `csv.DictReader()`;
+- `csv.DictWriter()`.
+
+Este capítulo enseña el núcleo práctico. Una fase posterior sobre Biblioteca Estándar podrá revisar opciones más amplias y personalizaciones del módulo.
+
+## 10. Abre archivos CSV con `newline=""`
+
+Cuando se pasa un objeto archivo al módulo `csv`, la documentación oficial recomienda abrirlo con `newline=""` para que el propio módulo CSV realice correctamente el manejo de nuevas líneas.
+
+```python
+with open("scores.csv", "r", encoding="utf-8", newline="") as file:
+ reader = csv.reader(file)
+```
+
+Mantén `encoding="utf-8"` explícito cuando UTF-8 forme parte del contrato de los datos.
+
+## 11. `csv.reader()` devuelve filas como listas
+
+Un reader básico trata cada registro como una secuencia de campos:
+
+```python
+import csv
+
+with open("scores.csv", "r", encoding="utf-8", newline="") as file:
+ reader = csv.reader(file)
+ for row in reader:
+ print(row)
+```
+
+Con el ejemplo anterior, las filas son listas como:
+
+```text
+['topic', 'score', 'status']
+['Functions', '91', 'complete']
+```
+
+Observa que `91` es una string.
+
+## 12. CSV normalmente no infiere los tipos de tu aplicación
+
+De forma predeterminada, `csv.reader()` devuelve los campos como strings. `DictReader` también entrega valores string para campos normales.
+
+Tu programa debe decidir qué conversiones forman parte del contrato:
+
+```python
+score = int(row[1])
+```
+
+La conversión puede fallar, por lo que este también es un límite de validación.
+
+## 13. `csv.writer()` da formato a las filas por ti
+
+No construyas registros CSV manualmente uniendo valores con comas.
+
+```python
+import csv
+
+rows = [
+ ["topic", "score"],
+ ["Functions", 91],
+ ["Files", 88],
+]
+
+with open("scores.csv", "w", encoding="utf-8", newline="") as file:
+ writer = csv.writer(file)
+ writer.writerows(rows)
+```
+
+El writer aplica las reglas configuradas de comillas y delimitadores CSV.
+
+## 14. `DictReader` da nombres a las columnas
+
+Cuando la primera fila es un encabezado, `DictReader` puede hacer el código más fácil de leer:
+
+```python
+import csv
+
+with open("scores.csv", "r", encoding="utf-8", newline="") as file:
+ reader = csv.DictReader(file)
+ for row in reader:
+ print(row["topic"], row["score"])
+```
+
+Los valores del encabezado se convierten en claves del diccionario.
+
+## 15. Los nombres de encabezado forman parte del contrato CSV
+
+El código que espera `row["score"]` depende de una columna llamada exactamente `score`.
+
+Si un productor cambia el encabezado a `final_score`, tu parser puede lanzar `KeyError` o tu validación puede rechazar el registro.
+
+Trata los nombres de columnas, los requisitos de orden, la elección del delimitador y los campos obligatorios como decisiones explícitas de interfaz.
+
+## 16. `DictWriter` hace explícitas las columnas de salida
+
+`DictWriter` requiere `fieldnames`, que definen el orden de las columnas:
+
+```python
+import csv
+
+fieldnames = ["topic", "score", "status"]
+
+with open("scores.csv", "w", encoding="utf-8", newline="") as file:
+ writer = csv.DictWriter(file, fieldnames=fieldnames)
+ writer.writeheader()
+ writer.writerow(
+ {"topic": "Files", "score": 88, "status": "complete"}
+ )
+```
+
+Esto suele ser más claro que los índices posicionales cuando la tabla tiene columnas con nombre.
+
+## 17. Los delimitadores varían
+
+La coma es el delimitador predeterminado del dialecto común estilo Excel, pero algunos contratos usan punto y coma, tabulaciones u otros delimitadores.
+
+```python
+reader = csv.reader(file, delimiter=";")
+```
+
+No adivines basándote en hábitos regionales ni en una sola fila de muestra. Conoce o documenta el contrato siempre que sea posible.
+
+## 18. Las comillas protegen campos con caracteres especiales
+
+El writer CSV puede entrecomillar campos que contienen delimitadores, caracteres de comillas o terminadores de línea.
+
+```python
+import csv
+
+row = ["Files", "Read, write, and validate"]
+```
+
+Con reglas normales de quoting, la coma dentro de la nota puede seguir formando parte de un solo campo.
+
+Esta es otra razón para dejar que `csv` genere el texto serializado.
+
+## 19. Parsing CSV y validación CSV son pasos diferentes
+
+Una fila puede ser CSV sintácticamente válido y aun así violar las reglas de la aplicación:
+
+```text
+topic,score
+Files,one hundred
+```
+
+El parser CSV puede devolver correctamente `"one hundred"`. Después, tu aplicación decide si `score` debe ser un entero.
+
+```text
+texto CSV
+ ↓ parser
+campos de la fila
+ ↓ conversión + validación
+registro confiable
+```
+
+## 20. JSON representa valores estructurados
+
+JSON es útil para objetos y arrays anidados, no solo tablas planas.
+
+```json
+{
+ "topic": "Files",
+ "score": 88,
+ "tags": ["io", "formats"],
+ "complete": true
+}
+```
+
+JSON es un formato de intercambio de datos. Se parece a algunos literales de Python, pero no es código fuente de Python.
+
+## 21. Los valores JSON principales se mapean a valores Python familiares
+
+Un mapeo útil para principiantes es:
+
+| JSON | Valor Python típico |
+|---|---|
+| object | `dict` |
+| array | `list` |
+| string | `str` |
+| number | `int` o `float` |
+| `true` / `false` | `True` / `False` |
+| `null` | `None` |
+
+El mapeo es lo bastante cercano para resultar familiar, pero las sintaxis no son intercambiables.
+
+## 22. La sintaxis JSON no es sintaxis de literal Python
+
+Estos tokens JSON están en minúsculas:
+
+```json
+{"active": true, "result": null}
+```
+
+Python usa:
+
+```python
+data = {"active": True, "result": None}
+```
+
+No analices JSON con `eval()`.
+
+## 23. `json.loads()` analiza una string JSON
+
+La `s` de `loads` es una buena ayuda de memoria cuando trabajas con un valor string:
+
+```python
+import json
+
+text = '{"topic": "Files", "score": 88}'
+data = json.loads(text)
+
+print(data["topic"])
+```
+
+`loads()` devuelve valores Python creados a partir del documento JSON.
+
+## 24. `json.dumps()` crea una string JSON
+
+`dumps()` serializa un valor Python compatible a una string con formato JSON:
+
+```python
+import json
+
+data = {"topic": "Files", "score": 88}
+text = json.dumps(data)
+
+print(text)
+```
+
+Serialización significa convertir un valor en memoria en una representación adecuada para almacenamiento o transporte.
+
+## 25. `json.load()` lee JSON desde un objeto archivo o similar
+
+Cuando el documento JSON ya está en un archivo de texto, usa `load()` con el archivo abierto:
+
+```python
+import json
+
+with open("profile.json", "r", encoding="utf-8") as file:
+ data = json.load(file)
+```
+
+`open()` gestiona el acceso al archivo. `json.load()` analiza el texto y lo convierte en valores Python.
+
+## 26. `json.dump()` escribe un valor JSON en un objeto archivo o similar
+
+```python
+import json
+
+data = {"topic": "Files", "complete": True}
+
+with open("profile.json", "w", encoding="utf-8") as file:
+ json.dump(data, file)
+```
+
+`json.dump()` escribe strings en el destino. En el uso común con archivos, abre ese destino en modo texto.
+
+## 27. `ensure_ascii=False` mantiene legible el texto no ASCII
+
+De forma predeterminada, el encoder JSON escapa los caracteres no ASCII. Cuando un archivo UTF-8 es el contrato explícito, `ensure_ascii=False` puede mantener esos caracteres legibles en el documento serializado:
+
+```python
+import json
+
+data = {"language": "Português"}
+
+with open("profile.json", "w", encoding="utf-8") as file:
+ json.dump(data, file, ensure_ascii=False)
+```
+
+La elección afecta a la representación, no al valor de la string Python después de una decodificación correcta.
+
+## 28. `indent` mejora la legibilidad humana
+
+El JSON con formato es útil para configuración, ejemplos y archivos que las personas inspeccionan manualmente:
+
+```python
+json.dump(data, file, ensure_ascii=False, indent=2)
+```
+
+La indentación aumenta el tamaño del archivo, así que una salida compacta puede ser mejor en algunas interfaces orientadas a máquinas. Elige según el contrato, no solo por estética.
+
+## 29. JSON no válido lanza `JSONDecodeError`
+
+Los errores de sintaxis en un documento JSON se informan con `json.JSONDecodeError`, una subclase de `ValueError`:
+
+```python
+import json
+
+text = '{"topic": "Files",}'
+
+try:
+ data = json.loads(text)
+except json.JSONDecodeError:
+ print("Invalid JSON")
+```
+
+Captúrala solo donde el programa tenga una política útil de recuperación o informe.
+
+
+El decoder de Python también tiene una extensión deliberada de interoperabilidad: de forma predeterminada, `json.loads()` acepta `NaN`, `Infinity` y `-Infinity` y los convierte en valores de punto flotante, aunque esos tokens no son JSON válido según la especificación interoperable de JSON. Por lo tanto, una llamada exitosa a `json.loads()` **no** demuestra por sí sola que la entrada cumpla el estándar JSON.
+
+Cuando el cumplimiento estricto del estándar forme parte del contrato, proporciona `parse_constant` con un callback que rechace esos valores explícitamente:
+
+```python
+import json
+
+
+def reject_nonstandard_constant(value: str):
+ raise ValueError(f"non-standard JSON constant: {value}")
+
+
+text = '{"value": NaN}'
+
+try:
+ data = json.loads(text, parse_constant=reject_nonstandard_constant)
+except ValueError as error:
+ print(error)
+```
+
+Aquí, el `ValueError` es lanzado deliberadamente por el callback. `JSONDecodeError` sigue representando errores comunes de sintaxis JSON, como la coma final del ejemplo anterior.
+
+
+El encoder tiene la preocupación de interoperabilidad correspondiente en la dirección inversa. De forma predeterminada, `json.dumps()` y `json.dump()` usan `allow_nan=True`, por lo que Python puede serializar valores de punto flotante no finitos como `NaN`, `Infinity` y `-Infinity`. Esos tokens están fuera del JSON compatible con el estándar y pueden ser rechazados por consumidores estrictos.
+
+Cuando la salida JSON estricta forme parte del contrato, establece `allow_nan=False`:
+
+```python
+import json
+
+data = {"value": float("nan")}
+
+try:
+ text = json.dumps(data, allow_nan=False)
+except ValueError as error:
+ print(error)
+```
+
+Con `allow_nan=False`, Python lanza `ValueError` en lugar de emitir una constante JSON no estándar. La misma opción está disponible en `json.dump()`.
+
+## 30. No todos los objetos Python son serializables a JSON de forma predeterminada
+
+El encoder predeterminado maneja estructuras comunes compatibles con JSON, pero los objetos arbitrarios no se convierten automáticamente.
+
+```python
+import json
+
+values = {1, 2, 3}
+json.dumps(values)
+```
+
+Un `set` no es un tipo JSON, por lo que esto lanza `TypeError` sin una transformación o personalización deliberada.
+
+Para código de principiantes, una transformación explícita suele ser más clara que un encoder personalizado.
+
+## 31. Un round trip JSON puede cambiar estructuras específicas de Python
+
+Los arrays JSON vuelven como listas. Eso significa que una tupla serializada como array no vuelve automáticamente como tupla:
+
+```python
+import json
+
+original = ("Files", "JSON")
+restored = json.loads(json.dumps(original))
+
+print(type(restored).__name__)
+```
+
+Salida:
+
+```text
+list
+```
+
+JSON representa tipos JSON, no todas las distinciones del modelo de objetos de Python.
+
+## 32. Las claves de objetos JSON son strings en el modelo de datos
+
+El encoder de Python acepta algunas claves básicas que no son strings y las convierte para JSON, pero los nombres de miembros de objetos JSON son strings.
+
+Por ello, un diccionario con claves no string puede no ser igual después de un round trip dump/load.
+
+Si el tipo de clave importa para tu aplicación, diseña esa representación de forma explícita.
+
+## 33. No añadas documentos JSON independientes con llamadas repetidas a `dump()`
+
+JSON no es un protocolo enmarcado. Escribir dos valores JSON de nivel superior uno detrás de otro no crea automáticamente un único documento JSON válido:
+
+```python
+json.dump(first, file)
+json.dump(second, file)
+```
+
+Si necesitas varios registros, elige un contenedor definido, como un único array JSON, u otro formato especificado explícitamente.
+
+## 34. Parsing no es validación
+
+Un parser responde si el texto sigue la sintaxis del formato y reconstruye valores.
+
+La validación responde si esos valores satisfacen las reglas del programa.
+
+```python
+import json
+
+data = json.loads('{"score": -50}')
+
+if not 0 <= data["score"] <= 100:
+ raise ValueError("score must be between 0 and 100")
+```
+
+El JSON es sintácticamente válido. El valor de la aplicación es inválido.
+
+## 35. Separa I/O, parsing y validación cuando el programa crezca
+
+Los programas pequeños pueden mantener estos pasos cerca, pero funciones claras ayudan cuando aumenta la complejidad:
+
+```text
+leer bytes/texto
+ ↓
+analizar formato
+ ↓
+validar valores
+ ↓
+transformar/usar datos
+```
+
+Esta separación facilita identificar si un fallo vino del acceso al archivo, la sintaxis del formato, la conversión de tipos o una regla de la aplicación.
+
+## 36. Ejemplo práctico: un registro TXT por línea
+
+El ejemplo ejecutable usa un directorio temporal solo para mantener limpios los tests del repositorio:
+
+```python
+import os
+import tempfile
+
+
+with tempfile.TemporaryDirectory() as directory:
+ path = os.path.join(directory, "topics.txt")
+
+ with open(path, "w", encoding="utf-8") as file:
+ file.write("Functions\n")
+ file.write("Files\n")
+ file.write("JSON\n")
+
+ with open(path, "r", encoding="utf-8") as file:
+ topics = [line.rstrip("\n") for line in file]
+
+ print(topics)
+```
+
+Salida:
+
+```text
+['Functions', 'Files', 'JSON']
+```
+
+Versión ejecutable: [`examples/text_records.py`](examples/text_records.py).
+
+## 37. Ejemplo práctico: diccionarios CSV y conversión explícita
+
+```python
+import csv
+import os
+import tempfile
+
+
+records = [
+ {"topic": "Functions", "score": 91, "note": "Clear flow"},
+ {"topic": "Files", "score": 88, "note": "Read, write, validate"},
+]
+
+with tempfile.TemporaryDirectory() as directory:
+ path = os.path.join(directory, "scores.csv")
+ fieldnames = ["topic", "score", "note"]
+
+ with open(path, "w", encoding="utf-8", newline="") as file:
+ writer = csv.DictWriter(file, fieldnames=fieldnames)
+ writer.writeheader()
+ writer.writerows(records)
+
+ with open(path, "r", encoding="utf-8", newline="") as file:
+ reader = csv.DictReader(file)
+ for row in reader:
+ score = int(row["score"])
+ print(f'{row["topic"]}: {score} - {row["note"]}')
+```
+
+Salida:
+
+```text
+Functions: 91 - Clear flow
+Files: 88 - Read, write, validate
+```
+
+Versión ejecutable: [`examples/csv_records.py`](examples/csv_records.py).
+
+## 38. Ejemplo práctico: escribir y leer un documento JSON
+
+```python
+import json
+import os
+import tempfile
+
+
+profile = {
+ "topic": "Files",
+ "score": 88,
+ "tags": ["io", "formats"],
+ "complete": True,
+}
+
+with tempfile.TemporaryDirectory() as directory:
+ path = os.path.join(directory, "profile.json")
+
+ with open(path, "w", encoding="utf-8") as file:
+ json.dump(profile, file, ensure_ascii=False, indent=2)
+
+ with open(path, "r", encoding="utf-8") as file:
+ restored = json.load(file)
+
+ print(restored["topic"])
+ print(restored["tags"])
+ print(restored["complete"])
+```
+
+Salida:
+
+```text
+Files
+['io', 'formats']
+True
+```
+
+Versión ejecutable: [`examples/json_document.py`](examples/json_document.py).
+
+## 39. Ejemplo práctico: manejar JSON no válido deliberadamente
+
+```python
+import json
+
+
+text = '{"topic": "Files",}'
+
+try:
+ data = json.loads(text)
+except json.JSONDecodeError:
+ print("Invalid JSON")
+else:
+ print(data)
+```
+
+Salida:
+
+```text
+Invalid JSON
+```
+
+Versión ejecutable: [`examples/handle_invalid_json.py`](examples/handle_invalid_json.py).
+
+## 40. Error común: tratar todo archivo de texto como CSV
+
+Un archivo de texto con prosa, líneas de log o un valor por línea no se convierte en CSV solo porque teóricamente podrían separarse campos.
+
+Usa CSV cuando el contrato sea realmente tabular y sus reglas de comillas y delimitadores sean apropiadas.
+
+Usa texto más simple cuando el texto simple sea el formato real.
+
+## 41. Error común: construir JSON manualmente
+
+Evita este estilo:
+
+```python
+text = '{"name": "' + name + '", "score": ' + str(score) + '}'
+```
+
+Escapar comillas, barras invertidas, caracteres de control, estructuras anidadas, booleanos y `null` se vuelve rápidamente propenso a errores.
+
+Construye valores Python y deja que `json.dumps()` o `json.dump()` los serialicen.
+
+## 42. Error común: confiar automáticamente en los datos analizados
+
+Un parsing correcto no demuestra que existan los campos obligatorios, que los tipos cumplan el contrato de la aplicación, que los rangos numéricos sean válidos o que las strings sean aceptables.
+
+Trata los datos de archivos y red como entrada:
+
+```text
+parsing correcto
+ ≠
+seguro y válido para todo uso
+```
+
+Valida las propiedades de las que tu programa realmente depende.
+
+## 43. Elegir entre TXT, CSV y JSON
+
+| Forma o necesidad | Buena elección inicial |
+|---|---|
+| Líneas simples legibles por personas | TXT |
+| Filas planas con columnas consistentes | CSV |
+| Objetos anidados, arrays, booleanos y nulls | JSON |
+| Datos ya gobernados por un contrato de formato externo | Usa el formato requerido |
+
+La extensión no es el factor decisivo. Lo son el modelo de datos y el contrato de interoperabilidad.
+
+## 44. Cuándo evitar inventar un formato de texto personalizado
+
+Un formato privado diminuto puede estar bien para una tarea pequeña y controlada. Se vuelve arriesgado cuando empiezas a añadir:
+
+- reglas de escape;
+- campos opcionales o repetidos;
+- delimitadores entrecomillados;
+- valores anidados;
+- versionado;
+- múltiples productores y consumidores independientes.
+
+En ese punto, un formato estándar normalmente aporta parsers probados e interoperabilidad más clara.
+
+## 45. Ejercicio
+
+Crea un programa llamado `study_export.py` con estos requisitos:
+
+1. Empieza con una lista de diccionarios que contengan `topic`, `score` y `complete`.
+2. Escribe los registros en `study.csv` con `csv.DictWriter`.
+3. Vuelve a abrir el CSV con `csv.DictReader`, convierte `score` a `int` y convierte `complete` de nuevo a `bool` con un mapeo explícito como `{"True": True, "False": False}`; rechaza texto inesperado en vez de usar `bool()` directamente.
+4. Construye una nueva lista con los registros convertidos.
+5. Escribe esa lista en `study.json` usando `json.dump()` con UTF-8, `ensure_ascii=False` e `indent=2`.
+6. Vuelve a abrir el JSON con `json.load()`.
+7. Muestra solo los temas cuyo score sea al menos 80.
+8. Usa `with` para cada operación real de archivo.
+
+Preguntas extra:
+
+- ¿Por qué se usa `newline=""` para el archivo CSV?
+- ¿Por qué el score del CSV debe convertirse explícitamente?
+- ¿Por qué `bool(row["complete"])` sería incorrecto cuando el texto CSV sea `"False"`?
+- ¿Qué excepción lanzaría una sintaxis JSON no válida?
+- ¿Por qué `split(",")` sería inseguro para una nota que contiene comas?
+- ¿Qué paso es parsing y qué paso es validación de la aplicación?
+
+## 46. Lista de revisión
+
+Antes de continuar, confirma que puedes responder sin adivinar:
+
+- ¿Cuál es la diferencia entre una extensión de archivo y un formato de datos?
+- ¿`.txt` define una única estructura universal de registros?
+- ¿Por qué CSV no debe analizarse con un split ingenuo por comas?
+- ¿Por qué se recomienda `newline=""` cuando se usa un objeto archivo con `csv`?
+- ¿Qué contienen de forma predeterminada las filas de `csv.reader()`?
+- ¿Por qué `DictReader` puede ser más claro que índices numéricos de columna?
+- ¿Cuál es la diferencia entre `json.load()` y `json.loads()`?
+- ¿Cuál es la diferencia entre `json.dump()` y `json.dumps()`?
+- ¿Qué valor JSON se corresponde con `None` de Python?
+- ¿Qué excepción indica sintaxis JSON no válida?
+- ¿Todo objeto Python puede serializarse automáticamente a JSON?
+- ¿Por qué parsing y validación son conceptos separados?
+
+## 47. Referencia rápida
+
+| Necesidad | Patrón |
+|---|---|
+| Leer texto UTF-8 simple | `open(path, "r", encoding="utf-8")` |
+| Leer filas CSV | `csv.reader(file)` |
+| Escribir filas CSV | `csv.writer(file)` |
+| Leer CSV con columnas nombradas | `csv.DictReader(file)` |
+| Escribir CSV con columnas nombradas | `csv.DictWriter(file, fieldnames=...)` |
+| Abrir un objeto archivo para CSV | `open(path, ..., encoding="utf-8", newline="")` |
+| Analizar string JSON | `json.loads(text)` |
+| Crear string JSON | `json.dumps(data)` |
+| Analizar archivo JSON | `json.load(file)` |
+| Escribir archivo JSON | `json.dump(data, file)` |
+| Conservar Unicode legible en la salida | `ensure_ascii=False` |
+| Formatear JSON | `indent=2` |
+| Sintaxis JSON no válida | `json.JSONDecodeError` |
+| Objeto incompatible con JSON al serializar | `TypeError` |
+
+Un pipeline predeterminado útil es:
+
+```text
+abrir de forma segura
+ ↓
+analizar con el parser del formato
+ ↓
+convertir y validar valores de la aplicación
+ ↓
+usar o transformar datos confiables
+```
+
+## Qué sigue
+
+El Capítulo 04 añade formatos comunes de datos textuales a la base de gestión de archivos. El último capítulo de la Fase 7, **Imports, Módulos y Paquetes**, pasará de datos almacenados en varios archivos a código Python organizado en varios archivos.
+
+```text
+excepciones
+ ↓
+señalización deliberada de excepciones
+ ↓
+tiempo de vida seguro de archivos
+ ↓
+límites de datos TXT / CSV / JSON
+ ↓
+imports / módulos / paquetes
+```
+
+## Referencias oficiales
+
+- Documentación `csv` de Python 3.14:
+- Documentación `json` de Python 3.14:
+- Tutorial de Python 3.14, Reading and Writing Files:
+- Tutorial de Python 3.14, Saving structured data with `json`:
diff --git a/errors-files-and-modules/04-txt-csv-and-json/README.md b/errors-files-and-modules/04-txt-csv-and-json/README.md
new file mode 100644
index 0000000..200d902
--- /dev/null
+++ b/errors-files-and-modules/04-txt-csv-and-json/README.md
@@ -0,0 +1,887 @@
+
+
+# Working with TXT, CSV, and JSON
+
+[🇺🇸 English](README.md) · [🇧🇷 Português](README.pt-BR.md) · [🇪🇸 Español](README.es.md)
+
+
+
+[← Back to Errors, Files, and Modules](../README.md) · [← Previous: Opening Files Safely with `open()` and `with`](../03-open-and-with/README.md)
+
+Opening a file safely is only half of the job. A program also needs to understand **how the data inside that file is organized**.
+
+A `.txt` file may contain one record per line, a CSV file may represent rows and columns, and a JSON document may represent nested objects and arrays. The file extension is a useful clue, but the real contract is the data format and the rules used to parse it.
+
+This chapter introduces plain text records, Python's `csv` module, and Python's `json` module. The goal is not to memorize every option. The goal is to choose a format deliberately, use the parser responsible for that format, and keep parsing separate from validation and business logic.
+
+**Estimated study time:** 120–160 minutes.
+
+**Python requirement:** Python 3.10 or newer. The `csv` and `json` behavior taught here was checked against the official Python 3.14 documentation.
+
+## Learning objectives
+
+By the end of this chapter, you should be able to:
+
+- explain the difference between a file extension and a data format;
+- use plain text when a simple line-oriented contract is enough;
+- explain why CSV should not be parsed with a naive `split(",")`;
+- read and write CSV rows with the standard-library `csv` module;
+- use `DictReader` and `DictWriter` when named columns improve clarity;
+- explain why CSV values normally arrive as strings and convert them deliberately;
+- open CSV files with `newline=""` and a known text encoding;
+- distinguish JSON objects, arrays, strings, numbers, booleans, and `null`;
+- use `json.load()`, `json.loads()`, `json.dump()`, and `json.dumps()` correctly;
+- handle invalid JSON with `json.JSONDecodeError` where recovery is meaningful;
+- distinguish parsing from validation;
+- choose TXT, CSV, or JSON according to the shape and contract of the data;
+- avoid hand-built parsers when a format-specific parser already exists.
+
+## 1. A file is a container; a format is a contract
+
+Chapter 03 focused on opening, reading, writing, and closing files. This chapter adds another question:
+
+```text
+bytes on storage
+ ↓ decoding
+text in Python
+ ↓ parsing
+structured Python values
+ ↓ validation
+values your program trusts
+```
+
+Opening a file answers **where the data comes from**. Parsing answers **what the text means**.
+
+These are related responsibilities, but they are not the same responsibility.
+
+## 2. The extension does not magically parse the contents
+
+A filename such as `topics.txt`, `scores.csv`, or `profile.json` communicates intent to humans and tools. Python does not automatically inspect the extension and turn the contents into the corresponding structure.
+
+You choose the appropriate operation:
+
+```python
+with open("topics.txt", "r", encoding="utf-8") as file:
+ text = file.read()
+```
+
+or a format-specific parser such as `csv.reader()` or `json.load()`.
+
+## 3. TXT means text, not one universal schema
+
+`.txt` usually means plain text, but there is no single universal TXT record format.
+
+All of these could be valid text-file contracts:
+
+```text
+Functions
+Exceptions
+Files
+```
+
+```text
+topic=Functions
+level=2
+active=true
+```
+
+```text
+2026-08-26 | Files | completed
+```
+
+The program and the producer of the file must agree on the rules.
+
+## 4. A simple TXT contract can be one record per line
+
+If every line is one independent text value, the format can remain intentionally simple:
+
+```python
+with open("topics.txt", "r", encoding="utf-8") as file:
+ topics = [line.rstrip("\n") for line in file]
+```
+
+Here the parser is small because the contract is small: each physical line represents one topic.
+
+## 5. Preserve meaningful whitespace deliberately
+
+Avoid using `strip()` automatically when spaces might belong to the data.
+
+```python
+clean_line = line.rstrip("\n")
+```
+
+This removes only the newline character named by the format decision above.
+
+If your format defines other normalization rules, apply those rules explicitly rather than treating all whitespace as disposable.
+
+## 6. Simple custom separators are still a format you must define
+
+Suppose a controlled text file contains one key-value pair per line:
+
+```text
+topic=Files
+level=2
+```
+
+A deliberate parser might split only at the first separator:
+
+```python
+key, value = line.rstrip("\n").split("=", 1)
+```
+
+The `1` matters if the value itself may contain `=` later.
+
+Once escaping, quoting, optional columns, nested data, or many edge cases appear, a standard format is usually a better choice than growing a private mini-language.
+
+## 7. CSV represents tabular records
+
+CSV is useful when the data naturally looks like rows with the same columns:
+
+```text
+topic,score,status
+Functions,91,complete
+Files,88,complete
+JSON,79,review
+```
+
+The name means comma-separated values, but real CSV data can use different delimiters and quoting rules. Python models those choices through CSV dialect and formatting options.
+
+## 8. Do not parse CSV with `split(",")`
+
+This looks tempting:
+
+```python
+columns = line.split(",")
+```
+
+but a valid field may itself contain a comma when quoted:
+
+```text
+topic,note
+Files,"Read, write, and validate"
+```
+
+A CSV parser understands delimiters, quotes, embedded newlines, and other format rules. A naive string split does not.
+
+## 9. Import the standard-library `csv` module
+
+The module is part of Python's standard library:
+
+```python
+import csv
+```
+
+It provides row-oriented APIs such as:
+
+- `csv.reader()`;
+- `csv.writer()`;
+- `csv.DictReader()`;
+- `csv.DictWriter()`.
+
+This chapter teaches the practical core. A later Standard Library phase can revisit broader module options and customization.
+
+## 10. Open CSV files with `newline=""`
+
+When a file object is passed to the `csv` module, the official documentation recommends opening it with `newline=""` so the CSV module can perform its own newline handling correctly.
+
+```python
+with open("scores.csv", "r", encoding="utf-8", newline="") as file:
+ reader = csv.reader(file)
+```
+
+Keep `encoding="utf-8"` explicit when UTF-8 is the data contract.
+
+## 11. `csv.reader()` returns rows as lists
+
+A basic reader treats each record as a sequence of fields:
+
+```python
+import csv
+
+with open("scores.csv", "r", encoding="utf-8", newline="") as file:
+ reader = csv.reader(file)
+ for row in reader:
+ print(row)
+```
+
+With the earlier sample, rows are lists such as:
+
+```text
+['topic', 'score', 'status']
+['Functions', '91', 'complete']
+```
+
+Notice that `91` is a string.
+
+## 12. CSV does not normally infer your application types
+
+By default, `csv.reader()` returns fields as strings. `DictReader` also gives string values for ordinary fields.
+
+Your program must decide which conversions are part of its contract:
+
+```python
+score = int(row[1])
+```
+
+Conversion can fail, so this is also a validation boundary.
+
+## 13. `csv.writer()` formats rows for you
+
+Do not build CSV records manually by joining values with commas.
+
+```python
+import csv
+
+rows = [
+ ["topic", "score"],
+ ["Functions", 91],
+ ["Files", 88],
+]
+
+with open("scores.csv", "w", encoding="utf-8", newline="") as file:
+ writer = csv.writer(file)
+ writer.writerows(rows)
+```
+
+The writer applies the configured CSV quoting and delimiter rules.
+
+## 14. `DictReader` gives columns names
+
+When the first row is a header, `DictReader` can make code easier to read:
+
+```python
+import csv
+
+with open("scores.csv", "r", encoding="utf-8", newline="") as file:
+ reader = csv.DictReader(file)
+ for row in reader:
+ print(row["topic"], row["score"])
+```
+
+The header values become dictionary keys.
+
+## 15. Header names are part of the CSV contract
+
+Code that expects `row["score"]` depends on a column named exactly `score`.
+
+If a producer changes the header to `final_score`, your parser may raise `KeyError` or your validation may reject the record.
+
+Treat column names, order requirements, delimiter choices, and required fields as explicit interface decisions.
+
+## 16. `DictWriter` makes output columns explicit
+
+`DictWriter` requires `fieldnames`, which define the output column order:
+
+```python
+import csv
+
+fieldnames = ["topic", "score", "status"]
+
+with open("scores.csv", "w", encoding="utf-8", newline="") as file:
+ writer = csv.DictWriter(file, fieldnames=fieldnames)
+ writer.writeheader()
+ writer.writerow(
+ {"topic": "Files", "score": 88, "status": "complete"}
+ )
+```
+
+This is often clearer than positional indexes when the table has named columns.
+
+## 17. Delimiters vary
+
+Comma is the default delimiter for the usual Excel-style dialect, but some data contracts use semicolons, tabs, or other delimiters.
+
+```python
+reader = csv.reader(file, delimiter=";")
+```
+
+Do not guess from regional habits or from one sample row. Know or document the contract whenever possible.
+
+## 18. Quoting protects fields containing special characters
+
+The CSV writer can quote fields that contain delimiters, quote characters, or line terminators.
+
+```python
+import csv
+
+row = ["Files", "Read, write, and validate"]
+```
+
+With normal quoting rules, the comma inside the note can remain part of one field.
+
+This is another reason to let `csv` generate the serialized text.
+
+## 19. CSV parsing and CSV validation are different steps
+
+A row can be syntactically valid CSV and still violate your application's rules:
+
+```text
+topic,score
+Files,one hundred
+```
+
+The CSV parser can correctly return `"one hundred"`. Your application then decides whether `score` must be an integer.
+
+```text
+CSV text
+ ↓ parser
+row fields
+ ↓ conversion + validation
+trusted record
+```
+
+## 20. JSON represents structured values
+
+JSON is useful for nested objects and arrays rather than only flat tables.
+
+```json
+{
+ "topic": "Files",
+ "score": 88,
+ "tags": ["io", "formats"],
+ "complete": true
+}
+```
+
+JSON is a data interchange format. It resembles some Python literals, but it is not Python source code.
+
+## 21. Core JSON values map to familiar Python values
+
+A useful beginner mapping is:
+
+| JSON | Typical Python value |
+|---|---|
+| object | `dict` |
+| array | `list` |
+| string | `str` |
+| number | `int` or `float` |
+| `true` / `false` | `True` / `False` |
+| `null` | `None` |
+
+This mapping is close enough to feel familiar, but the syntaxes are not interchangeable.
+
+## 22. JSON syntax is not Python literal syntax
+
+These JSON tokens are lowercase:
+
+```json
+{"active": true, "result": null}
+```
+
+Python uses:
+
+```python
+data = {"active": True, "result": None}
+```
+
+Do not parse JSON with `eval()`.
+
+## 23. `json.loads()` parses a JSON string
+
+The `s` in `loads` is a useful memory aid for working with a string value:
+
+```python
+import json
+
+text = '{"topic": "Files", "score": 88}'
+data = json.loads(text)
+
+print(data["topic"])
+```
+
+`loads()` returns Python values created from the JSON document.
+
+## 24. `json.dumps()` creates a JSON string
+
+`dumps()` serializes a Python-compatible value into a JSON-formatted string:
+
+```python
+import json
+
+data = {"topic": "Files", "score": 88}
+text = json.dumps(data)
+
+print(text)
+```
+
+Serialization means converting an in-memory value into a representation suitable for storage or transport.
+
+## 25. `json.load()` reads JSON from a file-like object
+
+When the JSON document is already in a text file, use `load()` with the open file:
+
+```python
+import json
+
+with open("profile.json", "r", encoding="utf-8") as file:
+ data = json.load(file)
+```
+
+`open()` manages access to the file. `json.load()` parses the text into Python values.
+
+## 26. `json.dump()` writes one JSON value to a file-like object
+
+```python
+import json
+
+data = {"topic": "Files", "complete": True}
+
+with open("profile.json", "w", encoding="utf-8") as file:
+ json.dump(data, file)
+```
+
+`json.dump()` writes strings to the target file-like object. In ordinary file use, open that target in text mode.
+
+## 27. `ensure_ascii=False` keeps non-ASCII text readable
+
+By default, the JSON encoder escapes non-ASCII characters. When a UTF-8 file is your explicit contract, `ensure_ascii=False` can keep characters readable in the serialized document:
+
+```python
+import json
+
+data = {"language": "Português"}
+
+with open("profile.json", "w", encoding="utf-8") as file:
+ json.dump(data, file, ensure_ascii=False)
+```
+
+The choice affects representation, not the Python string value after correct decoding.
+
+## 28. `indent` improves human readability
+
+Pretty-printed JSON is useful for configuration, examples, and files people inspect manually:
+
+```python
+json.dump(data, file, ensure_ascii=False, indent=2)
+```
+
+Indentation increases file size, so compact output can be better for some machine-focused interfaces. Choose according to the contract, not aesthetics alone.
+
+## 29. Invalid JSON raises `JSONDecodeError`
+
+Syntax errors in a JSON document are reported with `json.JSONDecodeError`, a subclass of `ValueError`:
+
+```python
+import json
+
+text = '{"topic": "Files",}'
+
+try:
+ data = json.loads(text)
+except json.JSONDecodeError:
+ print("Invalid JSON")
+```
+
+Catch it only where the program has a useful recovery or reporting policy.
+
+
+Python's decoder also has a deliberate interoperability extension: by default, `json.loads()` accepts `NaN`, `Infinity`, and `-Infinity` and converts them to floating-point values, even though those tokens are not valid JSON according to the interoperable JSON specification. Therefore, a successful `json.loads()` call is **not** by itself proof that the input is standards-compliant JSON.
+
+When strict standards compliance is part of the contract, provide `parse_constant` with a callback that rejects those values explicitly:
+
+```python
+import json
+
+
+def reject_nonstandard_constant(value: str):
+ raise ValueError(f"non-standard JSON constant: {value}")
+
+
+text = '{"value": NaN}'
+
+try:
+ data = json.loads(text, parse_constant=reject_nonstandard_constant)
+except ValueError as error:
+ print(error)
+```
+
+Here the `ValueError` is raised deliberately by the callback. `JSONDecodeError` still represents ordinary JSON syntax errors such as the trailing comma in the earlier example.
+
+
+The encoder has the matching interoperability concern in the other direction. By default, `json.dumps()` and `json.dump()` use `allow_nan=True`, so Python can serialize non-finite floating-point values as `NaN`, `Infinity`, and `-Infinity`. Those tokens are outside standards-compliant JSON and may be rejected by strict consumers.
+
+When strict JSON output is part of the contract, set `allow_nan=False`:
+
+```python
+import json
+
+data = {"value": float("nan")}
+
+try:
+ text = json.dumps(data, allow_nan=False)
+except ValueError as error:
+ print(error)
+```
+
+With `allow_nan=False`, Python raises `ValueError` instead of emitting a non-standard JSON constant. The same option is available with `json.dump()`.
+
+## 30. Not every Python object is JSON serializable by default
+
+The default encoder handles common JSON-compatible structures, but arbitrary objects are not automatically converted.
+
+```python
+import json
+
+values = {1, 2, 3}
+json.dumps(values)
+```
+
+A `set` is not a JSON type, so this raises `TypeError` unless you deliberately transform or customize the value.
+
+For beginner code, explicit transformation is usually clearer than a custom encoder.
+
+## 31. A JSON round trip may change some Python-specific structure
+
+JSON arrays map back to lists. That means a tuple serialized as an array does not return as a tuple automatically:
+
+```python
+import json
+
+original = ("Files", "JSON")
+restored = json.loads(json.dumps(original))
+
+print(type(restored).__name__)
+```
+
+Output:
+
+```text
+list
+```
+
+JSON represents JSON types, not every distinction in Python's object model.
+
+## 32. JSON object keys are strings in the data model
+
+Python's encoder accepts some non-string basic dictionary keys and converts them for JSON, but JSON object member names are strings.
+
+Therefore, a dictionary with non-string keys may not compare equal after a dump/load round trip.
+
+If key type matters to your application, design that representation explicitly.
+
+## 33. Do not append independent JSON documents with repeated `dump()` calls
+
+JSON is not a framed protocol. Writing two top-level JSON values back-to-back does not automatically create one valid JSON document:
+
+```python
+json.dump(first, file)
+json.dump(second, file)
+```
+
+If you need multiple records, choose a defined container such as one JSON array, or a different explicitly specified format.
+
+## 34. Parsing is not validation
+
+A parser answers whether the text follows the syntax of the format and reconstructs values.
+
+Validation answers whether those values satisfy your program's rules.
+
+```python
+import json
+
+data = json.loads('{"score": -50}')
+
+if not 0 <= data["score"] <= 100:
+ raise ValueError("score must be between 0 and 100")
+```
+
+The JSON is syntactically valid. The application value is invalid.
+
+## 35. Separate I/O, parsing, and validation when the program grows
+
+Small programs can keep these steps close together, but clear functions help as complexity grows:
+
+```text
+read bytes/text
+ ↓
+parse format
+ ↓
+validate values
+ ↓
+transform/use data
+```
+
+This separation makes it easier to identify whether a failure came from file access, format syntax, type conversion, or a business rule.
+
+## 36. Practical example: one TXT record per line
+
+The executable example uses a temporary directory only to keep repository tests clean:
+
+```python
+import os
+import tempfile
+
+
+with tempfile.TemporaryDirectory() as directory:
+ path = os.path.join(directory, "topics.txt")
+
+ with open(path, "w", encoding="utf-8") as file:
+ file.write("Functions\n")
+ file.write("Files\n")
+ file.write("JSON\n")
+
+ with open(path, "r", encoding="utf-8") as file:
+ topics = [line.rstrip("\n") for line in file]
+
+ print(topics)
+```
+
+Output:
+
+```text
+['Functions', 'Files', 'JSON']
+```
+
+Executable version: [`examples/text_records.py`](examples/text_records.py).
+
+## 37. Practical example: CSV dictionaries and explicit conversion
+
+```python
+import csv
+import os
+import tempfile
+
+
+records = [
+ {"topic": "Functions", "score": 91, "note": "Clear flow"},
+ {"topic": "Files", "score": 88, "note": "Read, write, validate"},
+]
+
+with tempfile.TemporaryDirectory() as directory:
+ path = os.path.join(directory, "scores.csv")
+ fieldnames = ["topic", "score", "note"]
+
+ with open(path, "w", encoding="utf-8", newline="") as file:
+ writer = csv.DictWriter(file, fieldnames=fieldnames)
+ writer.writeheader()
+ writer.writerows(records)
+
+ with open(path, "r", encoding="utf-8", newline="") as file:
+ reader = csv.DictReader(file)
+ for row in reader:
+ score = int(row["score"])
+ print(f'{row["topic"]}: {score} - {row["note"]}')
+```
+
+Output:
+
+```text
+Functions: 91 - Clear flow
+Files: 88 - Read, write, validate
+```
+
+Executable version: [`examples/csv_records.py`](examples/csv_records.py).
+
+## 38. Practical example: write and read a JSON document
+
+```python
+import json
+import os
+import tempfile
+
+
+profile = {
+ "topic": "Files",
+ "score": 88,
+ "tags": ["io", "formats"],
+ "complete": True,
+}
+
+with tempfile.TemporaryDirectory() as directory:
+ path = os.path.join(directory, "profile.json")
+
+ with open(path, "w", encoding="utf-8") as file:
+ json.dump(profile, file, ensure_ascii=False, indent=2)
+
+ with open(path, "r", encoding="utf-8") as file:
+ restored = json.load(file)
+
+ print(restored["topic"])
+ print(restored["tags"])
+ print(restored["complete"])
+```
+
+Output:
+
+```text
+Files
+['io', 'formats']
+True
+```
+
+Executable version: [`examples/json_document.py`](examples/json_document.py).
+
+## 39. Practical example: handle invalid JSON deliberately
+
+```python
+import json
+
+
+text = '{"topic": "Files",}'
+
+try:
+ data = json.loads(text)
+except json.JSONDecodeError:
+ print("Invalid JSON")
+else:
+ print(data)
+```
+
+Output:
+
+```text
+Invalid JSON
+```
+
+Executable version: [`examples/handle_invalid_json.py`](examples/handle_invalid_json.py).
+
+## 40. Common mistake: treating every text file as CSV
+
+A text file containing prose, log lines, or one value per line does not become CSV merely because fields could theoretically be separated.
+
+Use CSV when the contract is genuinely tabular and its quoting/delimiter rules are appropriate.
+
+Use simpler text when simpler text is the actual format.
+
+## 41. Common mistake: manually constructing JSON
+
+Avoid this style:
+
+```python
+text = '{"name": "' + name + '", "score": ' + str(score) + '}'
+```
+
+Escaping quotes, backslashes, control characters, nested structures, booleans, and `null` quickly becomes error-prone.
+
+Build Python values, then let `json.dumps()` or `json.dump()` serialize them.
+
+## 42. Common mistake: trusting parsed data automatically
+
+Successful parsing does not prove that required fields exist, types match your application contract, numeric ranges are valid, or strings are acceptable.
+
+Treat file and network data as input:
+
+```text
+parse successfully
+ ≠
+safe and valid for every use
+```
+
+Validate the properties your program actually depends on.
+
+## 43. Choosing among TXT, CSV, and JSON
+
+| Shape or need | Good starting choice |
+|---|---|
+| Simple human-readable lines | TXT |
+| Flat rows with consistent columns | CSV |
+| Nested objects, arrays, booleans, and nulls | JSON |
+| Data already governed by an external format contract | Use that required format |
+
+The extension is not the deciding factor. The data model and interoperability contract are.
+
+## 44. When to avoid inventing a custom text format
+
+A tiny private format can be fine for a tiny controlled task. It becomes risky when you start adding:
+
+- escaping rules;
+- optional or repeated fields;
+- quoted delimiters;
+- nested values;
+- versioning;
+- multiple independent producers and consumers.
+
+At that point, a standard format usually buys you tested parsers and clearer interoperability.
+
+## 45. Exercise
+
+Create a program called `study_export.py` with these requirements:
+
+1. Start with a list of dictionaries containing `topic`, `score`, and `complete`.
+2. Write the records to `study.csv` with `csv.DictWriter`.
+3. Reopen the CSV with `csv.DictReader`, convert `score` to `int`, and convert `complete` back to `bool` with an explicit mapping such as `{"True": True, "False": False}`; reject unexpected text instead of using `bool()` directly.
+4. Build a new list containing the converted records.
+5. Write that list to `study.json` using `json.dump()` with UTF-8, `ensure_ascii=False`, and `indent=2`.
+6. Reopen the JSON with `json.load()`.
+7. Print only the topics whose score is at least 80.
+8. Use `with` for every real file operation.
+
+Extra questions:
+
+- Why is `newline=""` used for the CSV file?
+- Why must the CSV score be converted explicitly?
+- Why would `bool(row["complete"])` be wrong when the CSV text is `"False"`?
+- What exception would invalid JSON syntax raise?
+- Why would `split(",")` be unsafe for a note containing commas?
+- Which step is parsing, and which step is application validation?
+
+## 46. Review checklist
+
+Before continuing, confirm that you can answer these without guessing:
+
+- What is the difference between a file extension and a data format?
+- Does `.txt` define one universal record structure?
+- Why should CSV not be parsed with a naive comma split?
+- Why is `newline=""` recommended when a file object is used with `csv`?
+- What do `csv.reader()` rows contain by default?
+- Why might `DictReader` be clearer than numeric column indexes?
+- What is the difference between `json.load()` and `json.loads()`?
+- What is the difference between `json.dump()` and `json.dumps()`?
+- What JSON value maps to Python `None`?
+- What exception indicates invalid JSON syntax?
+- Can every Python object be serialized to JSON automatically?
+- Why are parsing and validation separate concepts?
+
+## 47. Quick reference
+
+| Need | Pattern |
+|---|---|
+| Read plain UTF-8 text | `open(path, "r", encoding="utf-8")` |
+| Read CSV rows | `csv.reader(file)` |
+| Write CSV rows | `csv.writer(file)` |
+| Read CSV with named columns | `csv.DictReader(file)` |
+| Write CSV with named columns | `csv.DictWriter(file, fieldnames=...)` |
+| Open a CSV file object | `open(path, ..., encoding="utf-8", newline="")` |
+| Parse JSON string | `json.loads(text)` |
+| Create JSON string | `json.dumps(data)` |
+| Parse JSON file | `json.load(file)` |
+| Write JSON file | `json.dump(data, file)` |
+| Preserve readable Unicode output | `ensure_ascii=False` |
+| Pretty-print JSON | `indent=2` |
+| Invalid JSON syntax | `json.JSONDecodeError` |
+| JSON-incompatible object during serialization | `TypeError` |
+
+A useful default pipeline is:
+
+```text
+open safely
+ ↓
+parse with the format-aware parser
+ ↓
+convert and validate application values
+ ↓
+use or transform trusted data
+```
+
+## What comes next
+
+Chapter 04 adds common text-data formats to the file-management foundation. The final Phase 7 chapter, **Imports, Modules, and Packages**, will move from data stored across files to Python code organized across files.
+
+```text
+exceptions
+ ↓
+deliberate exception signaling
+ ↓
+safe file lifetime
+ ↓
+TXT / CSV / JSON data boundaries
+ ↓
+imports / modules / packages
+```
+
+## Official references
+
+- Python 3.14 `csv` documentation:
+- Python 3.14 `json` documentation:
+- Python 3.14 tutorial, Reading and Writing Files:
+- Python 3.14 tutorial, Saving structured data with `json`:
diff --git a/errors-files-and-modules/04-txt-csv-and-json/README.pt-BR.md b/errors-files-and-modules/04-txt-csv-and-json/README.pt-BR.md
new file mode 100644
index 0000000..3885098
--- /dev/null
+++ b/errors-files-and-modules/04-txt-csv-and-json/README.pt-BR.md
@@ -0,0 +1,887 @@
+
+
+# Trabalhando com TXT, CSV e JSON
+
+[🇺🇸 English](README.md) · [🇧🇷 Português](README.pt-BR.md) · [🇪🇸 Español](README.es.md)
+
+
+
+[← Voltar para Erros, Arquivos e Módulos](../README.pt-BR.md) · [← Anterior: Abrindo Arquivos com Segurança com `open()` e `with`](../03-open-and-with/README.pt-BR.md)
+
+Abrir um arquivo com segurança é apenas metade do trabalho. Um programa também precisa entender **como os dados dentro desse arquivo estão organizados**.
+
+Um arquivo `.txt` pode conter um registro por linha, um CSV pode representar linhas e colunas e um documento JSON pode representar objetos e arrays aninhados. A extensão é uma pista útil, mas o contrato real é o formato dos dados e as regras usadas para interpretá-los.
+
+Este capítulo apresenta registros de texto simples, o módulo `csv` do Python e o módulo `json` do Python. O objetivo não é memorizar todas as opções. O objetivo é escolher um formato deliberadamente, usar o parser responsável por esse formato e manter parsing separado de validação e lógica da aplicação.
+
+**Tempo estimado de estudo:** 120–160 minutos.
+
+**Requisito de Python:** Python 3.10 ou mais recente. O comportamento de `csv` e `json` ensinado aqui foi verificado na documentação oficial do Python 3.14.
+
+## Objetivos de aprendizagem
+
+Ao final deste capítulo, você deverá conseguir:
+
+- explicar a diferença entre uma extensão de arquivo e um formato de dados;
+- usar texto simples quando um contrato orientado por linhas for suficiente;
+- explicar por que CSV não deve ser interpretado com um `split(",")` ingênuo;
+- ler e escrever linhas CSV com o módulo `csv` da biblioteca padrão;
+- usar `DictReader` e `DictWriter` quando colunas nomeadas melhorarem a clareza;
+- explicar por que valores CSV normalmente chegam como strings e convertê-los deliberadamente;
+- abrir arquivos CSV com `newline=""` e uma codificação de texto conhecida;
+- distinguir objetos, arrays, strings, números, booleanos e `null` em JSON;
+- usar `json.load()`, `json.loads()`, `json.dump()` e `json.dumps()` corretamente;
+- tratar JSON inválido com `json.JSONDecodeError` quando houver recuperação significativa;
+- distinguir parsing de validação;
+- escolher TXT, CSV ou JSON de acordo com a forma e o contrato dos dados;
+- evitar parsers feitos à mão quando já existe um parser específico para o formato.
+
+## 1. Um arquivo é um contêiner; um formato é um contrato
+
+O Capítulo 03 se concentrou em abrir, ler, escrever e fechar arquivos. Este capítulo acrescenta outra pergunta:
+
+```text
+bytes no armazenamento
+ ↓ decodificação
+texto no Python
+ ↓ parsing
+valores Python estruturados
+ ↓ validação
+valores nos quais o programa confia
+```
+
+Abrir um arquivo responde **de onde os dados vêm**. Fazer parsing responde **o que o texto significa**.
+
+São responsabilidades relacionadas, mas não são a mesma responsabilidade.
+
+## 2. A extensão não interpreta magicamente o conteúdo
+
+Um nome como `topics.txt`, `scores.csv` ou `profile.json` comunica intenção a pessoas e ferramentas. Python não inspeciona automaticamente a extensão e transforma o conteúdo na estrutura correspondente.
+
+Você escolhe a operação apropriada:
+
+```python
+with open("topics.txt", "r", encoding="utf-8") as file:
+ text = file.read()
+```
+
+ou um parser específico do formato, como `csv.reader()` ou `json.load()`.
+
+## 3. TXT significa texto, não um único esquema universal
+
+`.txt` normalmente significa texto simples, mas não existe um formato universal de registros TXT.
+
+Todos estes podem ser contratos válidos de arquivo de texto:
+
+```text
+Functions
+Exceptions
+Files
+```
+
+```text
+topic=Functions
+level=2
+active=true
+```
+
+```text
+2026-08-26 | Files | completed
+```
+
+O programa e quem produz o arquivo precisam concordar sobre as regras.
+
+## 4. Um contrato TXT simples pode ter um registro por linha
+
+Se cada linha for um valor de texto independente, o formato pode permanecer intencionalmente simples:
+
+```python
+with open("topics.txt", "r", encoding="utf-8") as file:
+ topics = [line.rstrip("\n") for line in file]
+```
+
+Aqui o parser é pequeno porque o contrato é pequeno: cada linha física representa um tópico.
+
+## 5. Preserve espaços significativos deliberadamente
+
+Evite usar `strip()` automaticamente quando espaços puderem fazer parte dos dados.
+
+```python
+clean_line = line.rstrip("\n")
+```
+
+Isso remove somente o caractere de nova linha definido pela decisão de formato acima.
+
+Se o seu formato definir outras regras de normalização, aplique-as explicitamente em vez de tratar todo espaço em branco como descartável.
+
+## 6. Separadores personalizados simples ainda formam um formato que precisa ser definido
+
+Suponha que um arquivo controlado contenha um par chave-valor por linha:
+
+```text
+topic=Files
+level=2
+```
+
+Um parser deliberado pode dividir apenas no primeiro separador:
+
+```python
+key, value = line.rstrip("\n").split("=", 1)
+```
+
+O `1` importa se o próprio valor puder conter `=` depois.
+
+Quando aparecem escape, aspas, colunas opcionais, dados aninhados ou muitos casos de borda, um formato padrão normalmente é melhor do que fazer crescer uma minilinguagem privada.
+
+## 7. CSV representa registros tabulares
+
+CSV é útil quando os dados naturalmente se parecem com linhas que possuem as mesmas colunas:
+
+```text
+topic,score,status
+Functions,91,complete
+Files,88,complete
+JSON,79,review
+```
+
+O nome significa valores separados por vírgula, mas dados CSV reais podem usar delimitadores e regras de aspas diferentes. Python modela essas escolhas por dialetos e opções de formatação CSV.
+
+## 8. Não interprete CSV com `split(",")`
+
+Isto parece tentador:
+
+```python
+columns = line.split(",")
+```
+
+mas um campo válido pode conter uma vírgula quando estiver entre aspas:
+
+```text
+topic,note
+Files,"Read, write, and validate"
+```
+
+Um parser CSV entende delimitadores, aspas, novas linhas embutidas e outras regras do formato. Um simples split de string não entende.
+
+## 9. Importe o módulo `csv` da biblioteca padrão
+
+O módulo faz parte da biblioteca padrão do Python:
+
+```python
+import csv
+```
+
+Ele fornece APIs orientadas por linhas, como:
+
+- `csv.reader()`;
+- `csv.writer()`;
+- `csv.DictReader()`;
+- `csv.DictWriter()`.
+
+Este capítulo ensina o núcleo prático. Uma fase posterior sobre Biblioteca Padrão poderá revisitar opções mais amplas e personalizações do módulo.
+
+## 10. Abra arquivos CSV com `newline=""`
+
+Quando um objeto arquivo é passado ao módulo `csv`, a documentação oficial recomenda abri-lo com `newline=""` para que o próprio módulo CSV faça corretamente o tratamento de novas linhas.
+
+```python
+with open("scores.csv", "r", encoding="utf-8", newline="") as file:
+ reader = csv.reader(file)
+```
+
+Mantenha `encoding="utf-8"` explícito quando UTF-8 fizer parte do contrato dos dados.
+
+## 11. `csv.reader()` retorna linhas como listas
+
+Um reader básico trata cada registro como uma sequência de campos:
+
+```python
+import csv
+
+with open("scores.csv", "r", encoding="utf-8", newline="") as file:
+ reader = csv.reader(file)
+ for row in reader:
+ print(row)
+```
+
+Com o exemplo anterior, as linhas são listas como:
+
+```text
+['topic', 'score', 'status']
+['Functions', '91', 'complete']
+```
+
+Observe que `91` é uma string.
+
+## 12. CSV normalmente não infere os tipos da sua aplicação
+
+Por padrão, `csv.reader()` retorna campos como strings. `DictReader` também fornece valores string para campos comuns.
+
+Seu programa precisa decidir quais conversões fazem parte do contrato:
+
+```python
+score = int(row[1])
+```
+
+A conversão pode falhar, portanto esta também é uma fronteira de validação.
+
+## 13. `csv.writer()` formata as linhas para você
+
+Não construa registros CSV manualmente juntando valores com vírgulas.
+
+```python
+import csv
+
+rows = [
+ ["topic", "score"],
+ ["Functions", 91],
+ ["Files", 88],
+]
+
+with open("scores.csv", "w", encoding="utf-8", newline="") as file:
+ writer = csv.writer(file)
+ writer.writerows(rows)
+```
+
+O writer aplica as regras configuradas de aspas e delimitadores CSV.
+
+## 14. `DictReader` dá nomes às colunas
+
+Quando a primeira linha é um cabeçalho, `DictReader` pode tornar o código mais fácil de ler:
+
+```python
+import csv
+
+with open("scores.csv", "r", encoding="utf-8", newline="") as file:
+ reader = csv.DictReader(file)
+ for row in reader:
+ print(row["topic"], row["score"])
+```
+
+Os valores do cabeçalho tornam-se chaves do dicionário.
+
+## 15. Nomes de cabeçalho fazem parte do contrato CSV
+
+Código que espera `row["score"]` depende de uma coluna chamada exatamente `score`.
+
+Se um produtor alterar o cabeçalho para `final_score`, seu parser poderá levantar `KeyError` ou sua validação poderá rejeitar o registro.
+
+Trate nomes de colunas, requisitos de ordem, escolha de delimitador e campos obrigatórios como decisões explícitas de interface.
+
+## 16. `DictWriter` torna explícitas as colunas de saída
+
+`DictWriter` exige `fieldnames`, que definem a ordem das colunas:
+
+```python
+import csv
+
+fieldnames = ["topic", "score", "status"]
+
+with open("scores.csv", "w", encoding="utf-8", newline="") as file:
+ writer = csv.DictWriter(file, fieldnames=fieldnames)
+ writer.writeheader()
+ writer.writerow(
+ {"topic": "Files", "score": 88, "status": "complete"}
+ )
+```
+
+Isso costuma ser mais claro que índices posicionais quando a tabela possui colunas nomeadas.
+
+## 17. Delimitadores variam
+
+Vírgula é o delimitador padrão do dialeto comum no estilo Excel, mas alguns contratos usam ponto e vírgula, tabulação ou outros delimitadores.
+
+```python
+reader = csv.reader(file, delimiter=";")
+```
+
+Não adivinhe com base em hábitos regionais nem em uma única linha de exemplo. Conheça ou documente o contrato sempre que possível.
+
+## 18. Aspas protegem campos com caracteres especiais
+
+O writer CSV pode colocar entre aspas campos que contenham delimitadores, caracteres de aspas ou terminadores de linha.
+
+```python
+import csv
+
+row = ["Files", "Read, write, and validate"]
+```
+
+Com regras normais de quoting, a vírgula dentro da observação pode continuar fazendo parte de um único campo.
+
+Esse é outro motivo para deixar `csv` gerar o texto serializado.
+
+## 19. Parsing CSV e validação CSV são etapas diferentes
+
+Uma linha pode ser CSV sintaticamente válido e ainda violar as regras da aplicação:
+
+```text
+topic,score
+Files,one hundred
+```
+
+O parser CSV consegue retornar corretamente `"one hundred"`. Depois, sua aplicação decide se `score` precisa ser inteiro.
+
+```text
+texto CSV
+ ↓ parser
+campos da linha
+ ↓ conversão + validação
+registro confiável
+```
+
+## 20. JSON representa valores estruturados
+
+JSON é útil para objetos e arrays aninhados, e não apenas tabelas planas.
+
+```json
+{
+ "topic": "Files",
+ "score": 88,
+ "tags": ["io", "formats"],
+ "complete": true
+}
+```
+
+JSON é um formato de intercâmbio de dados. Ele lembra alguns literais Python, mas não é código-fonte Python.
+
+## 21. Valores JSON centrais mapeiam para valores Python conhecidos
+
+Um mapeamento útil para iniciantes é:
+
+| JSON | Valor Python típico |
+|---|---|
+| object | `dict` |
+| array | `list` |
+| string | `str` |
+| number | `int` ou `float` |
+| `true` / `false` | `True` / `False` |
+| `null` | `None` |
+
+O mapeamento é próximo o suficiente para parecer familiar, mas as sintaxes não são intercambiáveis.
+
+## 22. Sintaxe JSON não é sintaxe de literal Python
+
+Estes tokens JSON são minúsculos:
+
+```json
+{"active": true, "result": null}
+```
+
+Python usa:
+
+```python
+data = {"active": True, "result": None}
+```
+
+Não interprete JSON com `eval()`.
+
+## 23. `json.loads()` interpreta uma string JSON
+
+O `s` de `loads` é uma boa ajuda de memória para trabalhar com um valor string:
+
+```python
+import json
+
+text = '{"topic": "Files", "score": 88}'
+data = json.loads(text)
+
+print(data["topic"])
+```
+
+`loads()` retorna valores Python criados a partir do documento JSON.
+
+## 24. `json.dumps()` cria uma string JSON
+
+`dumps()` serializa um valor Python compatível para uma string formatada como JSON:
+
+```python
+import json
+
+data = {"topic": "Files", "score": 88}
+text = json.dumps(data)
+
+print(text)
+```
+
+Serialização significa converter um valor em memória para uma representação adequada a armazenamento ou transporte.
+
+## 25. `json.load()` lê JSON de um objeto arquivo ou similar
+
+Quando o documento JSON já está em um arquivo de texto, use `load()` com o arquivo aberto:
+
+```python
+import json
+
+with open("profile.json", "r", encoding="utf-8") as file:
+ data = json.load(file)
+```
+
+`open()` gerencia o acesso ao arquivo. `json.load()` interpreta o texto em valores Python.
+
+## 26. `json.dump()` escreve um valor JSON em um objeto arquivo ou similar
+
+```python
+import json
+
+data = {"topic": "Files", "complete": True}
+
+with open("profile.json", "w", encoding="utf-8") as file:
+ json.dump(data, file)
+```
+
+`json.dump()` escreve strings no alvo. No uso comum com arquivo, abra esse alvo em modo texto.
+
+## 27. `ensure_ascii=False` mantém texto não ASCII legível
+
+Por padrão, o encoder JSON escapa caracteres não ASCII. Quando um arquivo UTF-8 é o contrato explícito, `ensure_ascii=False` pode manter esses caracteres legíveis no documento serializado:
+
+```python
+import json
+
+data = {"language": "Português"}
+
+with open("profile.json", "w", encoding="utf-8") as file:
+ json.dump(data, file, ensure_ascii=False)
+```
+
+A escolha afeta a representação, não o valor da string Python depois de uma decodificação correta.
+
+## 28. `indent` melhora a leitura humana
+
+JSON formatado é útil para configuração, exemplos e arquivos inspecionados manualmente:
+
+```python
+json.dump(data, file, ensure_ascii=False, indent=2)
+```
+
+A indentação aumenta o tamanho do arquivo, então saída compacta pode ser melhor em algumas interfaces voltadas a máquinas. Escolha de acordo com o contrato, não apenas pela aparência.
+
+## 29. JSON inválido levanta `JSONDecodeError`
+
+Erros de sintaxe em um documento JSON são reportados com `json.JSONDecodeError`, uma subclasse de `ValueError`:
+
+```python
+import json
+
+text = '{"topic": "Files",}'
+
+try:
+ data = json.loads(text)
+except json.JSONDecodeError:
+ print("Invalid JSON")
+```
+
+Capture a exceção somente onde o programa tiver uma política útil de recuperação ou relatório.
+
+
+O decoder do Python também possui uma extensão deliberada de interoperabilidade: por padrão, `json.loads()` aceita `NaN`, `Infinity` e `-Infinity` e os converte em valores de ponto flutuante, embora esses tokens não sejam JSON válido segundo a especificação interoperável de JSON. Portanto, uma chamada bem-sucedida de `json.loads()` **não** prova, por si só, que a entrada está em conformidade com o padrão JSON.
+
+Quando a conformidade estrita com o padrão fizer parte do contrato, forneça `parse_constant` com um callback que rejeite esses valores explicitamente:
+
+```python
+import json
+
+
+def reject_nonstandard_constant(value: str):
+ raise ValueError(f"non-standard JSON constant: {value}")
+
+
+text = '{"value": NaN}'
+
+try:
+ data = json.loads(text, parse_constant=reject_nonstandard_constant)
+except ValueError as error:
+ print(error)
+```
+
+Aqui, o `ValueError` é levantado deliberadamente pelo callback. `JSONDecodeError` continua representando erros comuns de sintaxe JSON, como a vírgula final do exemplo anterior.
+
+
+O encoder tem a preocupação de interoperabilidade correspondente no caminho inverso. Por padrão, `json.dumps()` e `json.dump()` usam `allow_nan=True`, então o Python pode serializar valores de ponto flutuante não finitos como `NaN`, `Infinity` e `-Infinity`. Esses tokens estão fora do JSON compatível com o padrão e podem ser rejeitados por consumidores estritos.
+
+Quando a saída JSON estrita fizer parte do contrato, defina `allow_nan=False`:
+
+```python
+import json
+
+data = {"value": float("nan")}
+
+try:
+ text = json.dumps(data, allow_nan=False)
+except ValueError as error:
+ print(error)
+```
+
+Com `allow_nan=False`, o Python levanta `ValueError` em vez de emitir uma constante JSON não padronizada. A mesma opção está disponível em `json.dump()`.
+
+## 30. Nem todo objeto Python é serializável para JSON por padrão
+
+O encoder padrão lida com estruturas comuns compatíveis com JSON, mas objetos arbitrários não são convertidos automaticamente.
+
+```python
+import json
+
+values = {1, 2, 3}
+json.dumps(values)
+```
+
+Um `set` não é um tipo JSON, então isso levanta `TypeError` sem uma transformação ou personalização deliberada.
+
+Para código de iniciante, uma transformação explícita costuma ser mais clara que um encoder personalizado.
+
+## 31. Um round trip JSON pode alterar estruturas específicas do Python
+
+Arrays JSON voltam como listas. Portanto, uma tupla serializada como array não retorna automaticamente como tupla:
+
+```python
+import json
+
+original = ("Files", "JSON")
+restored = json.loads(json.dumps(original))
+
+print(type(restored).__name__)
+```
+
+Saída:
+
+```text
+list
+```
+
+JSON representa tipos JSON, não todas as distinções do modelo de objetos do Python.
+
+## 32. Chaves de objetos JSON são strings no modelo de dados
+
+O encoder do Python aceita algumas chaves básicas que não são strings e as converte para JSON, mas nomes de membros de objetos JSON são strings.
+
+Portanto, um dicionário com chaves não string pode não ser igual depois de um round trip dump/load.
+
+Se o tipo da chave importar para a aplicação, projete essa representação explicitamente.
+
+## 33. Não acrescente documentos JSON independentes com chamadas repetidas a `dump()`
+
+JSON não é um protocolo enquadrado. Escrever dois valores JSON de topo em sequência não cria automaticamente um único documento JSON válido:
+
+```python
+json.dump(first, file)
+json.dump(second, file)
+```
+
+Se você precisa de vários registros, escolha um contêiner definido, como um único array JSON, ou outro formato explicitamente especificado.
+
+## 34. Parsing não é validação
+
+Um parser responde se o texto segue a sintaxe do formato e reconstrói valores.
+
+Validação responde se esses valores satisfazem as regras do programa.
+
+```python
+import json
+
+data = json.loads('{"score": -50}')
+
+if not 0 <= data["score"] <= 100:
+ raise ValueError("score must be between 0 and 100")
+```
+
+O JSON é sintaticamente válido. O valor da aplicação é inválido.
+
+## 35. Separe I/O, parsing e validação quando o programa crescer
+
+Programas pequenos podem manter essas etapas próximas, mas funções claras ajudam quando a complexidade aumenta:
+
+```text
+ler bytes/texto
+ ↓
+interpretar formato
+ ↓
+validar valores
+ ↓
+transformar/usar dados
+```
+
+Essa separação facilita identificar se uma falha veio do acesso ao arquivo, da sintaxe do formato, da conversão de tipos ou de uma regra da aplicação.
+
+## 36. Exemplo prático: um registro TXT por linha
+
+O exemplo executável usa um diretório temporário apenas para manter os testes do repositório limpos:
+
+```python
+import os
+import tempfile
+
+
+with tempfile.TemporaryDirectory() as directory:
+ path = os.path.join(directory, "topics.txt")
+
+ with open(path, "w", encoding="utf-8") as file:
+ file.write("Functions\n")
+ file.write("Files\n")
+ file.write("JSON\n")
+
+ with open(path, "r", encoding="utf-8") as file:
+ topics = [line.rstrip("\n") for line in file]
+
+ print(topics)
+```
+
+Saída:
+
+```text
+['Functions', 'Files', 'JSON']
+```
+
+Versão executável: [`examples/text_records.py`](examples/text_records.py).
+
+## 37. Exemplo prático: dicionários CSV e conversão explícita
+
+```python
+import csv
+import os
+import tempfile
+
+
+records = [
+ {"topic": "Functions", "score": 91, "note": "Clear flow"},
+ {"topic": "Files", "score": 88, "note": "Read, write, validate"},
+]
+
+with tempfile.TemporaryDirectory() as directory:
+ path = os.path.join(directory, "scores.csv")
+ fieldnames = ["topic", "score", "note"]
+
+ with open(path, "w", encoding="utf-8", newline="") as file:
+ writer = csv.DictWriter(file, fieldnames=fieldnames)
+ writer.writeheader()
+ writer.writerows(records)
+
+ with open(path, "r", encoding="utf-8", newline="") as file:
+ reader = csv.DictReader(file)
+ for row in reader:
+ score = int(row["score"])
+ print(f'{row["topic"]}: {score} - {row["note"]}')
+```
+
+Saída:
+
+```text
+Functions: 91 - Clear flow
+Files: 88 - Read, write, validate
+```
+
+Versão executável: [`examples/csv_records.py`](examples/csv_records.py).
+
+## 38. Exemplo prático: escrever e ler um documento JSON
+
+```python
+import json
+import os
+import tempfile
+
+
+profile = {
+ "topic": "Files",
+ "score": 88,
+ "tags": ["io", "formats"],
+ "complete": True,
+}
+
+with tempfile.TemporaryDirectory() as directory:
+ path = os.path.join(directory, "profile.json")
+
+ with open(path, "w", encoding="utf-8") as file:
+ json.dump(profile, file, ensure_ascii=False, indent=2)
+
+ with open(path, "r", encoding="utf-8") as file:
+ restored = json.load(file)
+
+ print(restored["topic"])
+ print(restored["tags"])
+ print(restored["complete"])
+```
+
+Saída:
+
+```text
+Files
+['io', 'formats']
+True
+```
+
+Versão executável: [`examples/json_document.py`](examples/json_document.py).
+
+## 39. Exemplo prático: tratar JSON inválido deliberadamente
+
+```python
+import json
+
+
+text = '{"topic": "Files",}'
+
+try:
+ data = json.loads(text)
+except json.JSONDecodeError:
+ print("Invalid JSON")
+else:
+ print(data)
+```
+
+Saída:
+
+```text
+Invalid JSON
+```
+
+Versão executável: [`examples/handle_invalid_json.py`](examples/handle_invalid_json.py).
+
+## 40. Erro comum: tratar todo arquivo de texto como CSV
+
+Um arquivo de texto com prosa, linhas de log ou um valor por linha não vira CSV apenas porque teoricamente seria possível separar campos.
+
+Use CSV quando o contrato for realmente tabular e suas regras de aspas e delimitadores forem apropriadas.
+
+Use texto mais simples quando texto simples for o formato real.
+
+## 41. Erro comum: construir JSON manualmente
+
+Evite este estilo:
+
+```python
+text = '{"name": "' + name + '", "score": ' + str(score) + '}'
+```
+
+Escapar aspas, barras invertidas, caracteres de controle, estruturas aninhadas, booleanos e `null` rapidamente se torna sujeito a erros.
+
+Construa valores Python e deixe `json.dumps()` ou `json.dump()` serializá-los.
+
+## 42. Erro comum: confiar automaticamente nos dados interpretados
+
+Parsing bem-sucedido não prova que campos obrigatórios existem, tipos atendem ao contrato da aplicação, faixas numéricas são válidas ou strings são aceitáveis.
+
+Trate dados de arquivos e rede como entrada:
+
+```text
+parsing bem-sucedido
+ ≠
+seguro e válido para todo uso
+```
+
+Valide as propriedades das quais seu programa realmente depende.
+
+## 43. Escolhendo entre TXT, CSV e JSON
+
+| Forma ou necessidade | Boa escolha inicial |
+|---|---|
+| Linhas simples e legíveis por pessoas | TXT |
+| Linhas planas com colunas consistentes | CSV |
+| Objetos aninhados, arrays, booleanos e nulls | JSON |
+| Dados já governados por um contrato externo de formato | Use o formato exigido |
+
+A extensão não é o fator decisivo. O modelo dos dados e o contrato de interoperabilidade são.
+
+## 44. Quando evitar inventar um formato de texto personalizado
+
+Um pequeno formato privado pode funcionar em uma tarefa minúscula e controlada. Ele se torna arriscado quando você começa a adicionar:
+
+- regras de escape;
+- campos opcionais ou repetidos;
+- delimitadores entre aspas;
+- valores aninhados;
+- versionamento;
+- vários produtores e consumidores independentes.
+
+Nesse ponto, um formato padrão normalmente oferece parsers testados e interoperabilidade mais clara.
+
+## 45. Exercício
+
+Crie um programa chamado `study_export.py` com estes requisitos:
+
+1. Comece com uma lista de dicionários contendo `topic`, `score` e `complete`.
+2. Escreva os registros em `study.csv` com `csv.DictWriter`.
+3. Reabra o CSV com `csv.DictReader`, converta `score` para `int` e converta `complete` de volta para `bool` com um mapeamento explícito como `{"True": True, "False": False}`; rejeite textos inesperados em vez de usar `bool()` diretamente.
+4. Construa uma nova lista contendo os registros convertidos.
+5. Escreva essa lista em `study.json` usando `json.dump()` com UTF-8, `ensure_ascii=False` e `indent=2`.
+6. Reabra o JSON com `json.load()`.
+7. Exiba somente os tópicos cujo score seja pelo menos 80.
+8. Use `with` em toda operação real de arquivo.
+
+Perguntas extras:
+
+- Por que `newline=""` é usado no arquivo CSV?
+- Por que o score do CSV precisa ser convertido explicitamente?
+- Por que `bool(row["complete"])` estaria errado quando o texto do CSV fosse `"False"`?
+- Qual exceção uma sintaxe JSON inválida levanta?
+- Por que `split(",")` seria inseguro para uma observação contendo vírgulas?
+- Qual etapa é parsing e qual etapa é validação da aplicação?
+
+## 46. Checklist de revisão
+
+Antes de continuar, confirme que você consegue responder sem chutar:
+
+- Qual é a diferença entre uma extensão de arquivo e um formato de dados?
+- `.txt` define uma única estrutura universal de registros?
+- Por que CSV não deve ser interpretado com um split ingênuo por vírgula?
+- Por que `newline=""` é recomendado quando um objeto arquivo é usado com `csv`?
+- O que as linhas de `csv.reader()` contêm por padrão?
+- Por que `DictReader` pode ser mais claro que índices numéricos de coluna?
+- Qual é a diferença entre `json.load()` e `json.loads()`?
+- Qual é a diferença entre `json.dump()` e `json.dumps()`?
+- Qual valor JSON corresponde a `None` do Python?
+- Qual exceção indica sintaxe JSON inválida?
+- Todo objeto Python pode ser serializado automaticamente para JSON?
+- Por que parsing e validação são conceitos separados?
+
+## 47. Referência rápida
+
+| Necessidade | Padrão |
+|---|---|
+| Ler texto UTF-8 simples | `open(path, "r", encoding="utf-8")` |
+| Ler linhas CSV | `csv.reader(file)` |
+| Escrever linhas CSV | `csv.writer(file)` |
+| Ler CSV com colunas nomeadas | `csv.DictReader(file)` |
+| Escrever CSV com colunas nomeadas | `csv.DictWriter(file, fieldnames=...)` |
+| Abrir um objeto arquivo para CSV | `open(path, ..., encoding="utf-8", newline="")` |
+| Interpretar string JSON | `json.loads(text)` |
+| Criar string JSON | `json.dumps(data)` |
+| Interpretar arquivo JSON | `json.load(file)` |
+| Escrever arquivo JSON | `json.dump(data, file)` |
+| Preservar Unicode legível na saída | `ensure_ascii=False` |
+| Formatar JSON | `indent=2` |
+| Sintaxe JSON inválida | `json.JSONDecodeError` |
+| Objeto incompatível com JSON na serialização | `TypeError` |
+
+Um pipeline padrão útil é:
+
+```text
+abrir com segurança
+ ↓
+interpretar com o parser do formato
+ ↓
+converter e validar valores da aplicação
+ ↓
+usar ou transformar dados confiáveis
+```
+
+## O que vem depois
+
+O Capítulo 04 acrescenta formatos comuns de dados textuais à base de gerenciamento de arquivos. O último capítulo da Fase 7, **Imports, Módulos e Pacotes**, passará de dados armazenados em vários arquivos para código Python organizado em vários arquivos.
+
+```text
+exceções
+ ↓
+sinalização deliberada de exceções
+ ↓
+tempo de vida seguro de arquivos
+ ↓
+fronteiras de dados TXT / CSV / JSON
+ ↓
+imports / módulos / pacotes
+```
+
+## Referências oficiais
+
+- Documentação `csv` do Python 3.14:
+- Documentação `json` do Python 3.14:
+- Tutorial do Python 3.14, Reading and Writing Files:
+- Tutorial do Python 3.14, Saving structured data with `json`:
diff --git a/errors-files-and-modules/04-txt-csv-and-json/examples/csv_records.py b/errors-files-and-modules/04-txt-csv-and-json/examples/csv_records.py
new file mode 100644
index 0000000..3468102
--- /dev/null
+++ b/errors-files-and-modules/04-txt-csv-and-json/examples/csv_records.py
@@ -0,0 +1,24 @@
+import csv
+import os
+import tempfile
+
+
+records = [
+ {"topic": "Functions", "score": 91, "note": "Clear flow"},
+ {"topic": "Files", "score": 88, "note": "Read, write, validate"},
+]
+
+with tempfile.TemporaryDirectory() as directory:
+ path = os.path.join(directory, "scores.csv")
+ fieldnames = ["topic", "score", "note"]
+
+ with open(path, "w", encoding="utf-8", newline="") as file:
+ writer = csv.DictWriter(file, fieldnames=fieldnames)
+ writer.writeheader()
+ writer.writerows(records)
+
+ with open(path, "r", encoding="utf-8", newline="") as file:
+ reader = csv.DictReader(file)
+ for row in reader:
+ score = int(row["score"])
+ print(f'{row["topic"]}: {score} - {row["note"]}')
diff --git a/errors-files-and-modules/04-txt-csv-and-json/examples/handle_invalid_json.py b/errors-files-and-modules/04-txt-csv-and-json/examples/handle_invalid_json.py
new file mode 100644
index 0000000..4eee038
--- /dev/null
+++ b/errors-files-and-modules/04-txt-csv-and-json/examples/handle_invalid_json.py
@@ -0,0 +1,11 @@
+import json
+
+
+text = '{"topic": "Files",}'
+
+try:
+ data = json.loads(text)
+except json.JSONDecodeError:
+ print("Invalid JSON")
+else:
+ print(data)
diff --git a/errors-files-and-modules/04-txt-csv-and-json/examples/json_document.py b/errors-files-and-modules/04-txt-csv-and-json/examples/json_document.py
new file mode 100644
index 0000000..62d5475
--- /dev/null
+++ b/errors-files-and-modules/04-txt-csv-and-json/examples/json_document.py
@@ -0,0 +1,24 @@
+import json
+import os
+import tempfile
+
+
+profile = {
+ "topic": "Files",
+ "score": 88,
+ "tags": ["io", "formats"],
+ "complete": True,
+}
+
+with tempfile.TemporaryDirectory() as directory:
+ path = os.path.join(directory, "profile.json")
+
+ with open(path, "w", encoding="utf-8") as file:
+ json.dump(profile, file, ensure_ascii=False, indent=2)
+
+ with open(path, "r", encoding="utf-8") as file:
+ restored = json.load(file)
+
+ print(restored["topic"])
+ print(restored["tags"])
+ print(restored["complete"])
diff --git a/errors-files-and-modules/04-txt-csv-and-json/examples/text_records.py b/errors-files-and-modules/04-txt-csv-and-json/examples/text_records.py
new file mode 100644
index 0000000..ea2f67d
--- /dev/null
+++ b/errors-files-and-modules/04-txt-csv-and-json/examples/text_records.py
@@ -0,0 +1,16 @@
+import os
+import tempfile
+
+
+with tempfile.TemporaryDirectory() as directory:
+ path = os.path.join(directory, "topics.txt")
+
+ with open(path, "w", encoding="utf-8") as file:
+ file.write("Functions\n")
+ file.write("Files\n")
+ file.write("JSON\n")
+
+ with open(path, "r", encoding="utf-8") as file:
+ topics = [line.rstrip("\n") for line in file]
+
+ print(topics)
diff --git a/errors-files-and-modules/README.es.md b/errors-files-and-modules/README.es.md
index 044068c..76ff397 100644
--- a/errors-files-and-modules/README.es.md
+++ b/errors-files-and-modules/README.es.md
@@ -17,7 +17,7 @@ La Fase 7 comienza con el manejo de excepciones, continúa con la generación de
| [01. `try`, `except`, `else` y `finally`](01-try-except-else-finally/README.es.md) | Manejar fallos esperados en runtime manteniendo explícitas las rutas normal y de limpieza | Principiante a intermedio | Disponible |
| [02. Lanzar Excepciones y Excepciones Personalizadas](02-raise-and-custom-exceptions/README.es.md) | Señalar estados inválidos deliberadamente con `raise`, volver a lanzar o encadenar fallos de forma intencional e introducir excepciones personalizadas simples | Intermedio | Disponible |
| [03. `open()` y `with`](03-open-and-with/README.es.md) | Abrir, leer, escribir y añadir a archivos de texto gestionando recursos de forma segura con `with` | Principiante a intermedio | Disponible |
-| 04. TXT, CSV y JSON | Trabajar con formatos comunes de datos basados en texto y sus límites | Intermedio | Planificado |
+| [04. TXT, CSV y JSON](04-txt-csv-and-json/README.es.md) | Analizar, escribir, convertir y validar formatos comunes de datos textuales con herramientas específicas del formato | Intermedio | Disponible |
| 05. Imports, Módulos y Paquetes | Dividir código en archivos reutilizables y comprender el modelo de importación de Python | Intermedio | Planificado |
## Orientación de prerrequisitos
@@ -67,9 +67,9 @@ Al final de la Fase 7, deberías poder:
## Capítulo actual
-Continúa con [Abrir Archivos de Forma Segura con `open()` y `with`](03-open-and-with/README.es.md).
+Continúa con [Trabajar con TXT, CSV y JSON](04-txt-csv-and-json/README.es.md).
-Los Capítulos 01–02 establecen manejo y señalización deliberada de excepciones. El Capítulo 03 añade apertura de archivos de texto, encoding explícito, modos de archivo, lectura, escritura, append, errores de archivo específicos y limpieza gestionada por contexto. El próximo capítulo planificado es **TXT, CSV y JSON**.
+Los Capítulos 01–02 establecen manejo y señalización deliberada de excepciones. El Capítulo 03 añade un tiempo de vida seguro de archivos e I/O de texto. El Capítulo 04 añade contratos TXT orientados a líneas, readers y writers CSV, serialización y deserialización JSON, conversión explícita de tipos y límites entre parsing y validación. El próximo capítulo planificado es **Imports, Módulos y Paquetes**.
## Estructura del directorio
@@ -94,14 +94,23 @@ errors-files-and-modules/
│ ├── custom_exception.py
│ ├── exception_chaining.py
│ └── validate_score.py
-└── 03-open-and-with/
+├── 03-open-and-with/
+│ ├── README.md
+│ ├── README.pt-BR.md
+│ ├── README.es.md
+│ └── examples/
+│ ├── append_text.py
+│ ├── handle_missing_file.py
+│ └── write_and_read_text.py
+└── 04-txt-csv-and-json/
├── README.md
├── README.pt-BR.md
├── README.es.md
└── examples/
- ├── append_text.py
- ├── handle_missing_file.py
- └── write_and_read_text.py
+ ├── csv_records.py
+ ├── handle_invalid_json.py
+ ├── json_document.py
+ └── text_records.py
```
Los directorios de capítulos planificados se añaden únicamente cuando su contenido se publica realmente.
diff --git a/errors-files-and-modules/README.md b/errors-files-and-modules/README.md
index 67add40..3c0e7b8 100644
--- a/errors-files-and-modules/README.md
+++ b/errors-files-and-modules/README.md
@@ -17,7 +17,7 @@ Phase 7 starts with exception handling, then moves into deliberately raising exc
| [01. `try`, `except`, `else`, and `finally`](01-try-except-else-finally/README.md) | Handle expected runtime failures while keeping normal and cleanup paths explicit | Beginner to intermediate | Available |
| [02. Raising and Custom Exceptions](02-raise-and-custom-exceptions/README.md) | Signal invalid states deliberately with `raise`, re-raise or chain failures deliberately, and introduce simple custom exceptions | Intermediate | Available |
| [03. `open()` and `with`](03-open-and-with/README.md) | Open, read, write, and append text files while managing file resources safely with `with` | Beginner to intermediate | Available |
-| 04. TXT, CSV, and JSON | Work with common text-based data formats and their boundaries | Intermediate | Planned |
+| [04. TXT, CSV, and JSON](04-txt-csv-and-json/README.md) | Parse, write, convert, and validate common text-based data formats with format-aware tools | Intermediate | Available |
| 05. Imports, Modules, and Packages | Split code into reusable files and understand Python's import model | Intermediate | Planned |
## Prerequisite guidance
@@ -67,9 +67,9 @@ By the end of Phase 7, you should be able to:
## Current chapter
-Continue with [Opening Files Safely with `open()` and `with`](03-open-and-with/README.md).
+Continue with [Working with TXT, CSV, and JSON](04-txt-csv-and-json/README.md).
-Chapters 01–02 establish exception handling and deliberate exception signaling. Chapter 03 adds text-file opening, explicit encodings, file modes, reading, writing, appending, focused file errors, and context-managed cleanup. The next planned chapter is **TXT, CSV, and JSON**.
+Chapters 01–02 establish exception handling and deliberate exception signaling. Chapter 03 adds safe text-file lifetime and I/O. Chapter 04 adds line-oriented TXT contracts, CSV readers and writers, JSON serialization and deserialization, explicit type conversion, and parsing-versus-validation boundaries. The next planned chapter is **Imports, Modules, and Packages**.
## Directory structure
@@ -94,14 +94,23 @@ errors-files-and-modules/
│ ├── custom_exception.py
│ ├── exception_chaining.py
│ └── validate_score.py
-└── 03-open-and-with/
+├── 03-open-and-with/
+│ ├── README.md
+│ ├── README.pt-BR.md
+│ ├── README.es.md
+│ └── examples/
+│ ├── append_text.py
+│ ├── handle_missing_file.py
+│ └── write_and_read_text.py
+└── 04-txt-csv-and-json/
├── README.md
├── README.pt-BR.md
├── README.es.md
└── examples/
- ├── append_text.py
- ├── handle_missing_file.py
- └── write_and_read_text.py
+ ├── csv_records.py
+ ├── handle_invalid_json.py
+ ├── json_document.py
+ └── text_records.py
```
Planned chapter directories are added only when their content is actually published.
diff --git a/errors-files-and-modules/README.pt-BR.md b/errors-files-and-modules/README.pt-BR.md
index 4a0f99c..a172171 100644
--- a/errors-files-and-modules/README.pt-BR.md
+++ b/errors-files-and-modules/README.pt-BR.md
@@ -17,7 +17,7 @@ A Fase 7 começa com tratamento de exceções, avança para a criação delibera
| [01. `try`, `except`, `else` e `finally`](01-try-except-else-finally/README.pt-BR.md) | Tratar falhas esperadas em runtime mantendo explícitos os caminhos normal e de limpeza | Iniciante a intermediário | Disponível |
| [02. Levantando Exceções e Exceções Personalizadas](02-raise-and-custom-exceptions/README.pt-BR.md) | Sinalizar estados inválidos deliberadamente com `raise`, relançar ou encadear falhas de forma intencional e introduzir exceções personalizadas simples | Intermediário | Disponível |
| [03. `open()` e `with`](03-open-and-with/README.pt-BR.md) | Abrir, ler, escrever e acrescentar em arquivos de texto gerenciando recursos com segurança usando `with` | Iniciante a intermediário | Disponível |
-| 04. TXT, CSV e JSON | Trabalhar com formatos comuns de dados baseados em texto e seus limites | Intermediário | Planejado |
+| [04. TXT, CSV e JSON](04-txt-csv-and-json/README.pt-BR.md) | Interpretar, escrever, converter e validar formatos comuns de dados textuais com ferramentas específicas do formato | Intermediário | Disponível |
| 05. Imports, Módulos e Pacotes | Dividir código em arquivos reutilizáveis e entender o modelo de importação do Python | Intermediário | Planejado |
## Orientação de pré-requisitos
@@ -67,9 +67,9 @@ Ao final da Fase 7, você deverá conseguir:
## Capítulo atual
-Continue com [Abrindo Arquivos com Segurança com `open()` e `with`](03-open-and-with/README.pt-BR.md).
+Continue com [Trabalhando com TXT, CSV e JSON](04-txt-csv-and-json/README.pt-BR.md).
-Os Capítulos 01–02 estabelecem tratamento e sinalização deliberada de exceções. O Capítulo 03 acrescenta abertura de arquivos de texto, encoding explícito, modos de arquivo, leitura, escrita, append, erros de arquivo específicos e limpeza gerenciada por contexto. O próximo capítulo planejado é **TXT, CSV e JSON**.
+Os Capítulos 01–02 estabelecem tratamento e sinalização deliberada de exceções. O Capítulo 03 adiciona tempo de vida seguro de arquivos e I/O de texto. O Capítulo 04 acrescenta contratos TXT orientados por linhas, readers e writers CSV, serialização e desserialização JSON, conversão explícita de tipos e fronteiras entre parsing e validação. O próximo capítulo planejado é **Imports, Módulos e Pacotes**.
## Estrutura do diretório
@@ -94,14 +94,23 @@ errors-files-and-modules/
│ ├── custom_exception.py
│ ├── exception_chaining.py
│ └── validate_score.py
-└── 03-open-and-with/
+├── 03-open-and-with/
+│ ├── README.md
+│ ├── README.pt-BR.md
+│ ├── README.es.md
+│ └── examples/
+│ ├── append_text.py
+│ ├── handle_missing_file.py
+│ └── write_and_read_text.py
+└── 04-txt-csv-and-json/
├── README.md
├── README.pt-BR.md
├── README.es.md
└── examples/
- ├── append_text.py
- ├── handle_missing_file.py
- └── write_and_read_text.py
+ ├── csv_records.py
+ ├── handle_invalid_json.py
+ ├── json_document.py
+ └── text_records.py
```
Os diretórios dos capítulos planejados são adicionados somente quando seu conteúdo é realmente publicado.
diff --git a/scripts/example_manifest.txt b/scripts/example_manifest.txt
index bee7f65..b291c58 100644
--- a/scripts/example_manifest.txt
+++ b/scripts/example_manifest.txt
@@ -114,3 +114,7 @@ errors-files-and-modules/02-raise-and-custom-exceptions/examples/validate_score.
errors-files-and-modules/03-open-and-with/examples/append_text.py
errors-files-and-modules/03-open-and-with/examples/handle_missing_file.py
errors-files-and-modules/03-open-and-with/examples/write_and_read_text.py
+errors-files-and-modules/04-txt-csv-and-json/examples/csv_records.py
+errors-files-and-modules/04-txt-csv-and-json/examples/handle_invalid_json.py
+errors-files-and-modules/04-txt-csv-and-json/examples/json_document.py
+errors-files-and-modules/04-txt-csv-and-json/examples/text_records.py