El CSV no es «solo texto»: guía práctica del manejo de CSV en aplicaciones empresariales con C# (codificación de caracteres, compatibilidad con Excel, protección contra inyección)

· Actualizado el: · · CSharp, .NET, CSV, Excel, Codificación de caracteres, Integración de archivos, Desarrollo Windows, Consultoría técnica

Historial de revisiones (1 actualizaciones, última el 22 Aug 2026)

Registro de los cambios realizados en este artículo. Cuando se archivó una versión previa, sigue siendo legible mediante un enlace permanente con DOI.

Se ha sustituido la traducción, que estaba abreviada, por una traducción completa del artículo japonés en su versión actual: el texto crece un 29 %. Se han incorporado 2 apartados, 12 filas de tabla, 2 notas al pie y 1 bloque de código que no estaban en la edición anterior. El contenido no cambia respecto al original japonés; esta edición simplemente ya no lo resume. Además, los enlaces a otros artículos que ya tienen edición en español apuntan ahora a esa edición en lugar de a la japonesa. Leer la versión anterior a esta actualización (DOI: 10.5281/zenodo.21638346)
Primera publicación
Citar este artículo(DOI: 10.5281/zenodo.21638345)

Este artículo está archivado en Zenodo. A continuación se muestran tanto el DOI que siempre resuelve a la última versión como el DOI fijado a la versión que está leyendo.

Go Komura (2026). El CSV no es «solo texto»: guía práctica del manejo de CSV en aplicaciones empresariales con C# (codificación de caracteres, compatibilidad con Excel, protección contra inyección). KomuraSoft LLC. https://doi.org/10.5281/zenodo.21638345 https://comcomponent.com/es/blog/csv-file-handling-practical-guide/

DOI (última versión)
10.5281/zenodo.21638345
DOI (esta versión)
10.5281/zenodo.22053465

La integración de datos mediante CSV sigue siendo, hoy en día, una protagonista habitual en el mundo de las aplicaciones empresariales. Y precisamente porque parece «solo texto unido por comas», es también un terreno donde se repiten incidentes: un analizador (parser) casero que se rompe con una coma dentro de un campo, corrupción de caracteres al abrir el archivo en Excel, o la pérdida del cero inicial de un número de teléfono.

En este artículo, partiendo de una aplicación empresarial en C# que lee y escribe CSV, organizamos en el orden en que suelen surgir las dudas en la práctica: la especificación del CSV (RFC 4180) y sus dialectos reales, cómo decidir la codificación de caracteres, los problemas de compatibilidad con Excel, las medidas contra la inyección de CSV y las trampas operativas.

1. Primero, la conclusión (tabla de decisión)

Las decisiones de diseño del CSV se calculan hacia atrás a partir de «quién (o qué) va a abrir ese archivo». Este capítulo consta de dos partes: la tabla de decisión (1.1), para consultar «si el uso es este, entonces esto», y los principios (1.2), cinco reglas que aplican con independencia del uso. Desde la columna «Detalles» de la tabla de decisión puede saltar directamente al capítulo correspondiente, así que también puede usar el artículo leyendo solo los capítulos que necesite.

1.1 Decidir la codificación de caracteres según el uso (tabla de decisión)

Uso Primera opción de codificación Puntos clave de diseño Detalles
Una persona lo abre con doble clic en Excel UTF-8 (con BOM) Sin BOM, hay entornos en los que Excel interpreta mal la codificación y se corrompen los caracteres. Los problemas de pérdida de ceros iniciales y conversión a fecha no se evitan con la codificación 4.1 / Capítulo 5
Integración nueva entre sistemas UTF-8 (sin BOM) Especifique por escrito la codificación, las comillas, el código de salto de línea y si hay o no fila de encabezado. Indique también si hay o no BOM Capítulo 2 / 4.1
Integración con un sistema heredado Según las especificaciones de la contraparte (a menudo Shift_JIS) En .NET (Core) hace falta registrar CodePagesEncodingProvider para usar Shift_JIS. Acuerde de antemano el tratamiento de los caracteres dependientes del equipo 4.2
Integración por lotes de grandes volúmenes de datos Según las especificaciones Procese fila a fila mediante streaming en lugar de cargar todo en memoria. Diseñe también el control de exclusión y el tratamiento de archivos a medio escribir Capítulo 7
Exportar datos que incluyen entrada del usuario Según el uso Si no se neutralizan los valores que empiezan por = o +, puede llegar a ejecutarse una fórmula en el entorno de quien abra el archivo Capítulo 6
El propósito principal es que una persona lo vea o lo imprima en Excel ── Considere directamente generar xlsx en lugar de CSV (véanse las preguntas frecuentes) Capítulo 5

1.2 Principios generales aplicables a todos los casos

Antes que nada, las conclusiones comunes con independencia del uso.

  • El análisis (parseo) de CSV mediante String.Split(',') está roto a nivel de especificación, aunque parezca funcionar. Esto se debe a que no puede procesar comas, saltos de línea ni comillas dentro de un campo. Dentro del estándar de .NET, use TextFieldParser (Capítulo 3).
  • Los incidentes de codificación de caracteres se producen por «cómo los interpreta Excel». Actualmente, la opción segura para el CSV que una persona abrirá en Excel es UTF-8 con BOM. Además, existe la trampa de que, en .NET, si se añade o no el BOM depende de cómo se especifique el Encoding (Capítulo 4).
  • En .NET (Core), Shift_JIS no se puede usar sin un paquete adicional. Solo al registrar CodePagesEncodingProvider, del paquete System.Text.Encoding.CodePages, Encoding.GetEncoding("shift_jis") tiene éxito1. Es el punto clásico donde un procesamiento de CSV migrado desde .NET Framework lanza por primera vez una excepción, ya en producción (4.2).
  • La pérdida de ceros iniciales y la conversión a fecha no se pueden evitar desde el lado del CSV. El hecho importante es que ni siquiera envolver el valor entre comillas dobles lo evita (Capítulo 5).
  • Las aplicaciones que exportan entrada de usuario a CSV necesitan medidas contra la inyección de CSV. Excel interpreta como fórmula los campos que empiezan por = o + (Capítulo 6).

2. La especificación del CSV: RFC 4180 y los dialectos reales

El CSV cuenta con RFC 4180 como estándar de facto2. En la práctica, basta con tener presentes las siguientes cuatro reglas.

  1. El separador de registros es el salto de línea (CRLF) y el separador de campos es la coma.
  2. Si un campo contiene una coma, un salto de línea o una comilla doble, ese campo completo se envuelve entre comillas dobles.
  3. La comilla doble dentro de un campo se escapa duplicándola como "".
  4. Un campo que no necesita comillas puede llevarlas o no, indistintamente.

Es decir, la siguiente línea es un registro de tres campos.

1001,"Empresa Ejemplo S.A. Departamento de Ventas","La dirección introducida fue ""Tokio, distrito XX, 1-2-3"", y esta nota tiene una coma"

Y precisamente porque RFC 4180 es un «estándar de facto», el CSV real está lleno de dialectos: saltos de línea que son solo LF, ausencia de procesamiento de comillas, separadores que son tabulaciones o punto y coma, presencia o no de fila de encabezado… Por eso, incluir en el documento de especificaciones de la integración la frase «conforme a RFC 4180» junto con la codificación de caracteres, el BOM, el código de salto de línea y si hay o no fila de encabezado es, con diferencia, la tarea más rentable para prevenir problemas futuros.

3. Por qué no implementar Split(‘,’) por cuenta propia: la práctica de la lectura

Teniendo en cuenta las reglas del capítulo anterior, la razón por la que String.Split(',') se rompe es evidente: divide de más por una coma dentro de un campo, y un salto de línea dentro de comillas corta la línea a la mitad. Que «funcione» solo significa que «el archivo que llega ahora no tiene datos con comas»; puede romperse en cualquier momento según los datos.

Para leer correctamente dentro del estándar de .NET, puede usar Microsoft.VisualBasic.FileIO.TextFieldParser. El espacio de nombres es de Visual Basic, pero se usa con normalidad también desde C#3.

using Microsoft.VisualBasic.FileIO; // Microsoft.VisualBasic.Core (incluido en el SDK para escritorio de Windows)

using var parser = new TextFieldParser(path, System.Text.Encoding.UTF8)
{
    TextFieldType = FieldType.Delimited,
    HasFieldsEnclosedInQuotes = true, // Procesa correctamente los campos entre comillas
    TrimWhiteSpace = false, // El valor predeterminado es true (se eliminan silenciosamente los espacios al principio y al final). Desactívelo si el espacio en blanco tiene significado en los datos
};
parser.SetDelimiters(",");

while (!parser.EndOfData)
{
    try
    {
        string[]? fields = parser.ReadFields();
        if (fields is null) break;
        // Procesar fields[0], fields[1], ...
    }
    catch (MalformedLineException ex)
    {
        // Línea con formato incorrecto: ErrorLine / ErrorLineNumber permiten registrar el contenido y el número de línea
        logger.LogWarning("La línea {Line} del CSV tiene un formato incorrecto: {Content}",
            ex.LineNumber, parser.ErrorLine);
    }
}

La ventaja práctica de TextFieldParser, además del procesamiento de comillas (HasFieldsEnclosedInQuotes), es que puede detectar las líneas con formato incorrecto como MalformedLineException, con su número de línea3. En la importación de CSV en un entorno empresarial, el punto donde se bifurcan las especificaciones es «si una línea está mal, ¿se rechaza todo el archivo, o se omite solo esa línea y se informa?»; el diseño de este manejo de excepciones se traslada directamente a la especificación.

Si necesita mapeo entre columnas y objetos, conversión de tipos o rendimiento a escala de millones de filas, considere incorporar una librería de CSV con trayectoria contrastada. La más utilizada en .NET es CsvHelper (el paquete NuGet también se llama CsvHelper), que declara explícitamente su conformidad con RFC 4180 y tiene doble licencia MS-PL y Apache 2.0, lo que permite su uso comercial4. Cuenta con mapeo a clases, correspondencia de nombres de columna mediante ClassMap y lectura diferida con IEnumerable<T>, por lo que es la primera opción a la que migrar en cuanto se supera la etapa de «recibir string[] con TextFieldParser y convertir los tipos manualmente».

Sin embargo, más importante que qué librería elegir es qué comprobar al elegirla. Los cuatro puntos a verificar son: «procesamiento de comillas conforme a RFC 4180», «especificación de la codificación de caracteres», «tratamiento de líneas con formato incorrecto» y «posibilidad de lectura por streaming»; si se cumplen estos cuatro, en la práctica no se equivocará gravemente. Por el contrario, en entornos donde las normas internas restringen la incorporación de paquetes externos, decida primero si TextFieldParser es suficiente.

Para la escritura, como la especificación es más simple, desarrollarlo internamente es razonable, pero concentre siempre el procesamiento de escape en una sola función.

// El escape del lado de la escritura se concentra en esta única función
static string ToCsvField(string? value)
{
    value ??= string.Empty;
    bool needsQuoting = value.Contains(',') || value.Contains('"')
        || value.Contains('\r') || value.Contains('\n');
    return needsQuoting ? $"\"{value.Replace("\"", "\"\"")}\"" : value;
}

Qué hace esta función se entiende de un vistazo si se comparan la entrada y la salida.

Entrada (contenido de la cadena en C#) Valor devuelto por ToCsvField Motivo
Tokio Tokio No hay caracteres especiales, así que se devuelve tal cual
Empresa Ejemplo, Departamento de Ventas "Empresa Ejemplo, Departamento de Ventas" Contiene una coma, así que se envuelve todo
La dirección es "Tokio" "La dirección es ""Tokio""" Se reemplazan las comillas por "" y luego se envuelve todo
Línea 1(salto de línea)Línea 2 "Línea 1(salto de línea)Línea 2" Contiene un salto de línea, así que se envuelve. Al envolverlo, se lee correctamente como un solo campo
null (cadena vacía) Se convierte a cadena vacía mediante ??=

El orden «primero reemplazar, luego envolver» de la tercera fila es la clave. Si se invierte el orden, incluso las comillas que usted mismo añadió para envolver el campo se convierten en "" y todo se rompe. Si queda aunque sea un solo lugar donde «solo la columna de importes se genera a mano con string.Join», ese será el futuro escenario del incidente.

4. Codificación de caracteres: el comportamiento de Excel y las trampas de .NET

4.1 Para abrir en Excel, use UTF-8 con BOM

La mayoría de los casos de corrupción de caracteres en CSV se producen porque Excel interpreta mal la codificación del archivo. Si abre con doble clic un CSV en UTF-8 sin BOM (la marca de unos pocos bytes al principio del archivo), en algunos entornos se interpreta como ANSI (Shift_JIS en un entorno japonés) y el texto no ASCII queda completamente destruido. Con UTF-8 con BOM, en cambio, se reconoce correctamente como UTF-8, así que usar UTF-8 con BOM para el CSV que una persona abrirá con doble clic en Excel es, hoy en día, la opción segura.

La expresión «en algunos entornos» se debe a que hasta dónde Excel detecta automáticamente el UTF-8 sin BOM depende de su versión, su compilación y la configuración regional del sistema operativo, y no se puede afirmar con certeza a partir de qué versión se detecta siempre correctamente. Lo que sí puede tomarse como base para decidir es que el artículo de soporte vigente de Microsoft indica lo siguiente5.

Estado del archivo Indicación de Microsoft
UTF-8 con BOM Se abre con normalidad
UTF-8 sin BOM Abrirlo mediante Power Query (pestaña [Datos] > [Obtener datos] > [Desde archivo] > [Desde texto o CSV]), o especificar la codificación con el asistente de importación

Es decir, no está indicado oficialmente que el doble clic sobre un UTF-8 sin BOM siempre funcione. En una aplicación empresarial donde no se puede verificar de antemano la versión de Excel o la configuración regional de cada destinatario, mantener el archivo «con BOM, listo para abrirse con doble clic» reduce las consultas de soporte. Por el contrario, si el destino de la importación es un sistema, el BOM se convierte en 3 bytes de más que causan errores de análisis, así que se debe usar sin BOM.

El BOM en sí son los 3 bytes EF BB BF al principio del archivo. Si observa el inicio con un editor binario o con Format-Hex de PowerShell, puede determinar de inmediato con cuál de los dos se generó el archivo.

UTF-8 con BOM:   EF BB BF 44 61 74 65 2C ...   ← los primeros 3 bytes son EF BB BF, seguidos de "Date,"
UTF-8 sin BOM:   44 61 74 65 2C ...            ← empieza directamente con "Date,"

«Un archivo que debería tener BOM no empieza con EF BB BF» o «en el lado de la importación solo el primer nombre de columna no coincide (esos 3 bytes invisibles quedan pegados al principio del nombre de columna)»: ambos casos se pueden diagnosticar en 5 segundos con solo mirar esos 3 bytes.

A esto se suma una trampa del lado de .NET: que se añada el BOM o no depende de cómo se pase el Encoding.

// UTF-8 sin BOM: el valor predeterminado cuando se omite la codificación
File.WriteAllText(path, csv);

// UTF-8 con BOM: Encoding.UTF8 (la propiedad estática) está configurada para emitir el BOM
File.WriteAllText(path, csv, Encoding.UTF8);

// Si desea dejar la intención explícita, especificarlo mediante el constructor no da lugar a confusión
File.WriteAllText(path, csv, new UTF8Encoding(encoderShouldEmitUTF8Identifier: true));

Que el archivo resultante cambie según si se pasa Encoding.UTF8 o se omite es una particularidad que solo se descubre si ya se conoce6. Una vez que decida como especificación «sin BOM para la integración entre sistemas» y «con BOM para Excel», se recomienda dejar también la intención explícita en el código con new UTF8Encoding(...).

4.2 Para usar Shift_JIS en .NET (Core) hace falta registrarlo

En la integración con sistemas heredados, el CSV en Shift_JIS (página de códigos 932) sigue vigente hoy en día. Lo importante aquí es que .NET (Core) / .NET 5 y posteriores solo admiten por defecto un pequeño conjunto de codificaciones, como las de la familia Unicode y ASCII. Encoding.GetEncoding("shift_jis") lanzará una excepción hasta que se agregue el paquete System.Text.Encoding.CodePages y se registre CodePagesEncodingProvider1.

using System.Text;

// Registrar una sola vez al iniciar la aplicación (Program.cs, etc.)
Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);

// Con esto ya se puede obtener Shift_JIS (página de códigos 932)
Encoding sjis = Encoding.GetEncoding("shift_jis");

Es el punto clásico del incidente en el que una aplicación cuyo procesamiento de CSV se migró de la época de .NET Framework a .NET recibe por primera vez, ya en producción, un archivo en Shift_JIS y lanza una excepción. Los puntos a comprobar en la migración están recopilados en «Lista de verificación previa a la migración de .NET Framework a .NET».

Además, mientras se use Shift_JIS, no se pueden evitar los caracteres dependientes del equipo (como ① o ㈱), el problema de la virgulilla ondulada (波ダッシュ) ni la pérdida de caracteres que solo existen en Unicode. Los fundamentos de codificación de caracteres relacionados se explican en detalle en «Cómo funcionan la codificación de caracteres y la corrupción de texto en Windows» y «La práctica de la codificación de caracteres y los códigos de salto de línea en Windows».

5. Datos que se rompen al abrir en Excel: ceros iniciales, conversión a fecha, notación exponencial

Aunque la codificación de caracteres sea correcta, la visualización en Excel presenta otro grupo de problemas: Excel «interpreta» los valores al abrir el CSV.

Dato original Cómo se muestra en Excel Qué ha ocurrido
09012345678 (número de teléfono) 9012345678 Se interpreta como número y desaparece el cero inicial. Los 11 dígitos pasan a 10 y deja de servir como número de teléfono
007 (código de producto) 7 Igual que el caso anterior
1-1 (número de sufijo) 1 de enero Se interpreta como fecha
1234567890123456 (número de gestión de 16 dígitos) 1.23457E+15 Pasa a notación exponencial y se pierden los dígitos menos significativos

Y lo importante es que esto no se evita ni envolviendo el campo entre comillas dobles. Las comillas solo marcan un delimitador a nivel de sintaxis del CSV; Excel vuelve a interpretar el contenido de todos modos.

En la práctica, hay tres opciones de tratamiento.

  1. Pedir que se abra con el procedimiento correcto en Excel. En lugar de doble clic, si se importa mediante «Obtener datos (desde texto/CSV)» en Excel especificando el tipo de columna como «Texto», no se rompe. Vale la pena documentarlo en el manual de operación.
  2. Si el propósito principal es la visualización, generar xlsx. Como el formato de celda se puede controlar desde el lado que genera el archivo, todo este grupo de problemas desaparece de raíz. Consulte «Cómo generar salidas de informes en Excel» para saber cómo construir la salida de archivos de Excel. Tenga en cuenta que la automatización de Excel mediante COM en un servidor o servicio no es recomendable, ya que, como se explica en «El problema de que EXCEL.EXE permanece en ejecución», es un caldo de cultivo para procesos que quedan residentes; elija una salida basada en una librería.
  3. Generar en el formato ="007" es el último recurso. Es un truco que hace que Excel lo muestre como texto al abrirlo, pero, como CSV, se convierte en «un archivo no estándar con una fórmula dentro», y rompe cualquier destino de importación que no sea Excel. No lo use en archivos compartidos con otros sistemas.

6. Inyección de CSV: evitar que la entrada del usuario se convierta en una fórmula

Las aplicaciones que exportan a CSV valores introducidos por el usuario (nombre, notas, dirección, etc.) y hacen que se abran en Excel están expuestas a una vía de ataque llamada inyección de CSV. Excel interpreta como fórmula los campos que empiezan por =, +, -, @, etc., por lo que una entrada maliciosa (por ejemplo, una fórmula como =cmd|'/C calc'!A0, orientada a lanzar un proceso externo) puede llegar a ejecutarse en el entorno de otro usuario distinto que abra ese CSV7.

La base de la medida de protección es neutralizar en el momento de exportar los caracteres iniciales peligrosos.

// Se antepone una comilla simple a los campos que podrían interpretarse como fórmula.
// En un entorno japonés, los caracteres de ancho completo =+-@ también pueden interpretarse como inicio de fórmula, así que se incluyen
static string SanitizeForExcel(string value)
{
    if (value.Length > 0 && value[0]
        is '=' or '+' or '-' or '@' or '\t' or '\r' or '\n'
        or '=' or '+' or '-' or '@')
    {
        return "'" + value;
    }
    return value;
}

La comilla simple inicial es la marca que hace que Excel lo «trate como texto». Además, como la lista de caracteres iniciales peligrosos puede variar según la implementación y la versión de la hoja de cálculo, diseñar esta neutralización en la dirección de «dejar pasar tal cual solo si el carácter inicial coincide con esta lista blanca (alfanumérico, etc.)» es más resistente a casos no previstos. Sin embargo, hay que tener en cuenta que, si otro sistema importa ese CSV, la comilla simple permanece como parte del dato, por lo que también cabe la decisión de separar los archivos en «para abrir en Excel» y «para importar en un sistema». Para la validación de la entrada (por ejemplo, no permitir directamente que un valor empiece por =) y el diseño de seguridad de la aplicación en su conjunto, consulte «Lista de verificación mínima de seguridad para aplicaciones Windows».

7. Trampas operativas: dónde ocurren los incidentes más allá del formato

Por último, un resumen de los puntos donde ocurren incidentes en la práctica más allá de la propia sintaxis del CSV.

  • No haga depender el formato de números y fechas de la configuración regional del sistema operativo. value.ToString() se ve afectado por la configuración regional del sistema operativo. En una configuración regional donde el separador decimal es la coma, se generaría 1,5, lo que colisiona con el separador del CSV. Para la conversión destinada a integración de archivos, especifique explícitamente CultureInfo.InvariantCulture, y use para las fechas un formato fijo como yyyy-MM-dd. El diseño de fechas se trata en detalle en «Diseño de fecha, hora y zona horaria en aplicaciones empresariales».
  • Procese los grandes volúmenes de datos mediante streaming, pero si basta con «línea por línea» depende de la especificación. File.ReadAllLines carga todas las líneas en memoria como un array, por lo que no es adecuado para archivos grandes8. Aquí, sustituirlo por File.ReadLines (enumeración diferida) o por una lectura línea a línea con StreamReader solo está bien en archivos cuya especificación indique explícitamente que no se permiten saltos de línea dentro de un campo. En un CSV conforme a RFC 4180, que sí permite saltos de línea dentro de comillas, dividir por líneas corta un registro a la mitad. En ese caso, use TextFieldParser leyendo directamente desde la ruta del archivo (puede procesar sin cargar todo en memoria), o la lectura por streaming de una librería de CSV.
  • No haga que se lea, ni lea usted mismo, un «archivo a medio escribir». El lado que exporta escribe con un nombre de archivo temporal y luego lo renombra; el lado que importa comprueba la exclusión antes de leer. Esta forma básica de integración de archivos está recopilada en «Conceptos básicos del control de exclusión en la integración de archivos», y las precauciones al importar mediante supervisión de carpetas, en la «Guía práctica de FileSystemWatcher».
  • Prepárese para el aumento o la disminución de columnas. Especifique como parte del diseño si el mapeo se hará «por el nombre de columna de la fila de encabezado» o si será «orden de columna fijo, y se rechaza si la comprobación del número de columnas no coincide». Una referencia implícita mediante un número mágico como fields[7] se rompe en silencio ante una adición trivial de columna por parte de la contraparte de la integración.
  • Decida de antemano el tratamiento del salto de línea final y de las líneas vacías. Si hay o no un salto de línea después de la última línea, y si se omiten o se rechazan las líneas vacías, son puntos donde el comportamiento varía según la implementación del analizador. TextFieldParser omite las líneas vacías3.

Resumen

El CSV es un formato de integración lleno de dialectos, con apariencia de «simplemente separar por comas». Los puntos clave en la práctica son cuatro: use para la lectura un componente capaz de procesar comillas (no lo implemente usted mismo con Split), decida la codificación calculando hacia atrás desde quién va a abrirlo (en especial, Excel) y anote hasta el uso o no de BOM en la especificación, sepa que la interpretación de valores por parte de Excel (pérdida de ceros, conversión a fecha) no se puede evitar desde el lado del CSV, e incorpore medidas contra la inyección si exporta entrada de usuario. Solo con esto, la mayoría de los incidentes de integración de CSV se pueden eliminar en la etapa de diseño.

La investigación de la corrupción de caracteres o los daños en los datos de una integración CSV existente, la organización de las especificaciones de integración con sistemas heredados, y la implementación nueva de funciones de importación o exportación de CSV, suelen requerir decisiones tomadas viendo los archivos reales y las especificaciones de la contraparte de la integración, así que, si tiene dudas, consúltenos.

Artículos relacionados

Áreas de consultoría relacionadas

KomuraSoft LLC ofrece consultoría técnica sobre el desarrollo de aplicaciones empresariales que incluyen CSV e integración de archivos, la investigación del origen de la corrupción de caracteres o los daños en los datos de integraciones existentes, y la organización de las especificaciones de integración con sistemas heredados.

Referencias

  1. Microsoft Learn, CodePagesEncodingProvider Class. Sobre el hecho de que .NET Core solo admite por defecto ASCII, ISO-8859-1 y las codificaciones de la familia Unicode, y que las codificaciones de página de códigos como Shift_JIS (página de códigos 932) requieren registrar CodePagesEncodingProvider, del paquete System.Text.Encoding.CodePages, mediante Encoding.RegisterProvider 2

  2. IETF, RFC 4180 - Common Format and MIME Type for Comma-Separated Values (CSV) Files. La especificación de facto estándar del CSV. Sobre el procesamiento de comillas para la coma, el salto de línea y la comilla doble dentro de un campo, y el escape mediante ""

  3. Microsoft Learn, TextFieldParser Class. Sobre el análisis de texto en formato delimitado o de ancho fijo, el procesamiento de comillas mediante HasFieldsEnclosedInQuotes, la excepción MalformedLineException con ErrorLine/ErrorLineNumber en las líneas que no se pueden analizar, y el hecho de que ReadFields omite las líneas vacías.  2 3

  4. Documentación oficial de CsvHelper, CsvHelper. Sobre el hecho de que es una librería de lectura y escritura de CSV para .NET, que declara conformidad con RFC 4180, y que tiene doble licencia Microsoft Public License (MS-PL) y Apache License 2.0, lo que permite su uso comercial. 

  5. Soporte de Microsoft, Opening CSV UTF-8 files correctly in Excel. Sobre el hecho de que un CSV en UTF-8 guardado con BOM se abre con normalidad, y que, sin BOM, es necesario abrirlo desde la pestaña «Datos» > «Obtener datos» > «Desde archivo» > «Desde texto o CSV» (Power Query), o con el asistente de importación. 

  6. Microsoft Learn, UTF8Encoding Class. Sobre el control de la emisión del BOM (U+FEFF) mediante el parámetro encoderShouldEmitUTF8Identifier, y el hecho de que la instancia devuelta por la propiedad Encoding.UTF8 está configurada para emitir el BOM. 

  7. OWASP, CSV Injection. Sobre el ataque (inyección de fórmulas) en el que los campos que empiezan por =, +, -, @, tabulación o retorno de carro se interpretan como fórmula en la hoja de cálculo, y sus medidas de protección. 

  8. Microsoft Learn, File.ReadLines Method. Sobre el hecho de que, mientras ReadAllLines devuelve un array con todas las líneas, ReadLines devuelve una colección enumerable, por lo que incluso con archivos grandes se puede empezar a enumerar sin esperar a cargarlo todo. 

Artículos recientes con las mismas etiquetas para profundizar en temas cercanos.

Estas páginas sitúan el tema en un contexto más amplio de servicios y decisiones.

El artículo está directamente relacionado con los siguientes servicios.

Preguntas frecuentes

Preguntas habituales en las consultas sobre el tema del artículo.

¿Qué codificación de caracteres debería usar para el CSV?
La regla general, si el destinatario ya está definido, es ajustarse a las especificaciones de quien recibe el archivo. Si se puede decidir desde cero, un buen punto de partida es especificar en el documento de especificaciones UTF-8 con BOM para los archivos que las personas abrirán en Excel, y UTF-8 sin BOM para la integración entre sistemas. Si una integración con un sistema heredado exige Shift_JIS, es imprescindible acordar de antemano el tratamiento de los caracteres dependientes del equipo y de los caracteres externos, o de lo contrario surgirán después disputas sobre la responsabilidad de la corrupción de caracteres.
¿Conviene incorporar una librería de CSV, o basta con desarrollarlo internamente?
En cuanto a la lectura, dado que un String.Split casero no puede procesar correctamente ciertos casos según la especificación (comas, saltos de línea y comillas dentro de un campo), conviene usar algún componente ya existente. Dentro del propio estándar de .NET, TextFieldParser admite un procesamiento de comillas equivalente al de RFC 4180. Si además necesita mapeo entre columnas y objetos, conversión de tipos o rendimiento con grandes volúmenes de datos, considere incorporar una librería de CSV con trayectoria contrastada. Para la escritura, como la especificación es más simple, desarrollarlo internamente es razonable, pero prepare una única función común para el escape de comillas y haga que todo el código pase por ella.
¿Debería usar tabulaciones (TSV) en lugar de comas como separador?
Si los datos contienen comas con frecuencia (direcciones, nombres, importes monetarios, etc.), pasar a TSV reduce la frecuencia de tener que usar comillas y facilita la verificación visual. Sin embargo, el hecho de que las tabulaciones o los saltos de línea puedan aparecer en los datos sigue siendo el mismo, por lo que el procesamiento de comillas no deja de ser necesario. Tenga cuidado: «al ser TSV, no hace falta preocuparse por el separador» no es correcto. Si puede llegar a un acuerdo con la contraparte de la integración, especificar claramente en el documento de especificaciones la codificación de caracteres, las comillas, el código de salto de línea y si hay o no fila de encabezado es más eficaz para prevenir incidentes que el propio carácter separador.
Si el objetivo es que se abra en Excel, ¿debería generar un archivo de Excel en lugar de un CSV?
Si el propósito principal es que una persona lo vea o lo imprima en Excel, vale la pena considerar la generación en formato xlsx. El CSV es un formato en el que, en el momento de abrirlo en Excel, se produce la pérdida de ceros iniciales o la conversión automática a fecha, y no existe forma de evitarlo por completo desde el lado del CSV. Con xlsx, en cambio, el formato de celda puede controlarse desde el lado de la generación. Por otro lado, si el propósito principal es la importación a otro sistema y la visualización en Excel es secundaria, resulta más realista mantener el CSV e indicar como procedimiento operativo los «pasos de importación» (usar la función de importación de datos).

Perfil del autor

Página de presentación del autor del artículo.

Go Komura

Representante de KomuraSoft LLC

Especializado en desarrollo de software para Windows, consultoría técnica e investigación de fallos, sobre todo en proyectos con sistemas existentes y errores difíciles de reproducir.

Volver al blog