CSVParser.javajava.io.Reader y tokeniza datos CSV carácter por carácter, admitiendo campos entrecomillados, saltos de línea incrustados dentro de celdas entrecomilladas, comillas dobles escapadas (convención ""), separadores de campo configurables, mapeo de nombres de columnas de cabecera y detección de BOM UTF-8. Escrito por Kai Reinhard y H. Spiewok (2005), es anterior y evita dependencias externas de bibliotecas CSV.java.io.IOException / java.io.Reader — Entrada de flujo de caracteresjava.util.ArrayList, HashMap, List, Map — Almacenamiento de resultados e indexación de columnas de cabeceraorg.apache.commons.lang3.StringUtils — Verificación de cadenas en blanco en mensajes de errororg.slf4j.Logger — Registro de erroresEn lugar de usar expresiones regulares o un generador de analizadores, CSVParser implementa un analizador léxico carácter por carácter con un búfer de retroceso. Este diseño prioriza el control sobre el manejo de errores y el rendimiento para el subconjunto específico de formato CSV utilizado por ProjectForge.
enum Type { EOF, EOL, CHAR }
Tipos de token: Fin de archivo, Fin de línea o datos de carácter. Esto impulsa la máquina de estados del analizador.
int[] de 5 elementos (pushbackBuffer) con seguimiento de índice — permite la previsualización y el retroceso sin necesidad de que el Reader admita mark()/reset()\ncval para los tokens de carácter. Maneja \r\n (CRLF de Windows) como un único token EOLskipBOM() se llama durante la construcción para detectar y saltar una Marca de orden de bytes UTF-8 (\uFEFF) al inicio del archivo. Si no hay BOM, el primer carácter se empuja hacia atrás (unread). Esto permite el análisis correcto de archivos CSV exportados desde Microsoft Excel, que incluye un BOM para archivos UTF-8.
La lógica central de análisis CSV maneja estos casos:
| Caso | Comportamiento |
|---|---|
| Celda sin comillas | Los caracteres se acumulan hasta el separador o EOL |
Celda entrecomillada ("...") | Los caracteres dentro de las comillas se acumulan; las comillas deben cerrarse correctamente |
Comilla escapada ("") | Dos comillas dobles consecutivas dentro de una celda entrecomillada representan un carácter de comilla literal |
| Salto de línea incrustado | Los saltos de línea dentro de celdas entrecomilladas se conservan (valores de celda multilínea) |
| Espacio en blanco final | El espacio en blanco después de la comilla de cierre se omite; espera un separador o EOL a continuación |
| Comilla no terminada | Lanza una RuntimeException con un mensaje de error descriptivo que incluye el número de línea/columna |
Lee celdas hasta EOL o EOF, recogiéndolas en una List<String>. Devuelve null en EOF (no una lista vacía — los llamadores pueden distinguir el fin de archivo de las líneas vacías).
Para archivos CSV con una fila de cabecera, parseHeadCols() lee la primera línea y construye un colMap: Map<String, Integer> que asigna nombres de columna a su índice posicional. Las llamadas posteriores a getCell(List<String>, nombrecolumna) recuperan valores por nombre de columna en lugar de por posición. Esto permite el acceso a columnas con nombre similar a Excel.
Tres constantes de error distintas proporcionan diagnósticos específicos:
ERROR_UNEXPECTED_QUOTATIONMARK = "Comilla inesperada \" (solo permitida en celdas entrecomilladas)." ERROR_QUOTATIONMARK_MISSED_AT_END_OF_CELL = "Comilla \" faltante al final de la celda." ERROR_DELIMITER_OR_NEW_LINE_EXPECTED_AFTER_QUOTATION_MARK = "Se esperaba un delimitador o nueva línea después de la comilla." ERROR_UNEXPECTED_CHARACTER_AFTER_QUOTATION_MARK = "Carácter inesperado después de la comilla."
Cada mensaje se aumenta con números de línea y columna a través de createMessage().
CSVParser utiliza CSVWriter.DEFAULT_CSV_SEPARATOR_CHAR (';' — punto y coma) como su separador predeterminado. Esta es la convención CSV europea (Microsoft Excel en configuraciones regionales alemanas utiliza CSV delimitado por punto y coma). El separador es configurable a través de setCsvSeparatorChar().
parseLine() lee una línea y devuelve todas las celdas — adecuado para archivos de tamaño moderado pero no para CSV muy grandes (de varios GB)868d6abb7 2025 -> 2026 161d71602 WIP: CSVParser: caracteres BOM. dfb2378df WIP: CSVParser: multilíneas etc. 63081666f Encabezados de archivos fuente: 2024 -> 2025. a73905c14 Corregir errores tipográficos en directorios projectforge*/ Encontrados mediante codespell a72903e36 *.java, *.kt: StringBuffer -> StringBuilder. b6092df09 Copyright 2023 -> 2024 ab45d51fa Copyright 2001-2022 -> 2001-2023.