¿Cuáles son algunos consejos, trucos y errores al analizar y escribir archivos CSV?

El formato de archivo CSV ha existido durante décadas. Desafortunadamente, nunca se ha estandarizado completamente, por lo que las implementaciones variarán.

En 2005, el Grupo de trabajo de ingeniería de Internet publicó el RFC 4180, una especificación informativa que describe el formato CSV para el tipo MIME “text / csv”. Proporciona un conjunto bastante bueno de reglas a seguir, así como una gramática ABNF. Aquí está el enlace:

Formato común y tipo MIME para archivos de valores separados por comas (CSV)

Si va a escribir su propio analizador CSV, aquí hay algunos consejos que puedo darle:

  • Ni siquiera piense en usar una función de división de cadenas o una expresión regular para analizar el CSV en líneas y campos. La única forma de analizar CSV de manera confiable es carácter por carácter.
  • Los registros están delimitados por un CRLF en Windows y un LF en Unix. Sin embargo, los campos pueden contener caracteres CR o LF incrustados, por lo que su analizador debe analizar cada campo y saber cuándo no está dentro de un campo.
  • Los campos están delimitados por comas, pero debe proporcionar la opción de delimitación de pestañas, ya que es una alternativa común. (Por lo general, los datos de Excel que se copian en el portapapeles están delimitados por tabulaciones, no por comas).
  • Los campos solo deben incluirse entre comillas si contienen un campo incrustado o un delimitador de registro.
  • Las comillas incrustadas se escapan mediante comillas dobles, que es otra razón por la que debe analizar el carácter CSV por carácter. También te obliga a hacer una búsqueda anticipada de un personaje una vez dentro de un campo porque no puedes estar seguro de que la próxima cita que encuentres sea el final del campo o el escape de una cita incrustada.
  • Los espacios se consideran parte de un campo y no deben ignorarse.
  • El registro final del archivo no necesita tener un delimitador de registro. Tu código debe manejar eso.
  • El último campo del archivo no puede terminar con una coma.
  • Un archivo CSV puede tener una fila opcional de encabezados de columna. Debe permitir que la persona que llama le diga si los datos contienen una fila de encabezado o no. Si lo hace, entonces el número de campos en cada fila debe coincidir con el número de campos en el encabezado de la columna.
  • Trate de ser tan indulgente con los errores como sea posible.

Escribir CSV es en realidad un poco más fácil que leerlo. Solo tiene que asegurarse de que el campo a esté encerrado entre comillas si contiene un carácter delimitador, y que todas las comillas incrustadas dentro del campo se dupliquen.

Si puede usar una biblioteca acreditada para esto, puede ahorrarle algo de dolor. Por otro lado, he probado bibliotecas que no interpretaban CSV de la forma en que Excel las crea y tuvo que abandonarlas. (Uno, por ejemplo, ignoró erróneamente los espacios de campo al principio y al final.) Tanto si usa una biblioteca como si lanza su propio analizador CSV, asegúrese de escribir un buen conjunto de pruebas unitarias.

Actualmente estamos trabajando en el desarrollo de una aplicación de BI para una cadena de farmacias de EE. UU. Y la aplicación importa muchos informes en forma de CSV. El archivo tiene más de 80 campos y se deben analizar unos pocos cientos de filas de datos todos los días.

Comenzamos utilizando EPPlus ( http://epplus.codeplex.com ). Esta biblioteca de código abierto ayuda a leer y escribir en archivos de Excel. Como característica adicional, puede cargar archivos CSV. Una vez que el archivo CSV se carga en un archivo de Excel, podemos leer cada fila y convertirlo en un DataTable o DTO (objetos de transferencia de datos). Este enfoque funciona si el tamaño del archivo es bajo. Pero a medida que aumenta el tamaño, hay un impacto considerable en el rendimiento al cargar un archivo CSV como Excel. Fue agradable mientras duró, ya que solía reclamar que la aplicación admite la importación tanto de Excel como de CSV.

Toda la aplicación fue diseñada desde la perspectiva ‘cargar una vez y analizar más tarde’. Fue necesario un rediseño bastante serio para “leer una línea, analizarla y pasar a la siguiente línea”. Pero redujo el tiempo de importación y pudimos mostrar una buena barra de progreso que muestra el número de filas analizadas hasta el momento. Nos cambiamos a utilizar CsvHelper. Aquí hay algunos aprendizajes del proyecto.

  • Use una biblioteca en lugar de escribir su propio analizador. Hay muchas peculiaridades en el formato de archivo CSV que es mejor dejar que sean manejadas por una biblioteca diseñada para cuidarlas.
  • Si el tiempo de carga es superior a unos pocos segundos, cargue de forma asíncrona mientras proporciona comentarios continuos al usuario sobre el progreso de la importación y una forma de cancelar la importación.
  • Pasé algunas horas depurando la aplicación cuando encontré por primera vez un nombre que contenía comillas simples (D’souza). La biblioteca tiene ajustes de configuración para ignorar las comillas simples.
  • Siempre analizar manualmente los campos de fecha y hora. Lo que tiene sentido para ti, no tiene ningún sentido para la computadora.
  • Diseñe las columnas de la base de datos considerando todos los valores posibles que puede tomar un campo. Habría un intercambio entre la facilidad de análisis frente a la búsqueda. Esté preparado para cambiar el tipo de datos de columna a medida que el proyecto progresa. Tuve que cambiar un decimal a varchar cuando uno de los campos cambió para incluir un guión.
  • Informe al usuario sobre las líneas mal formateadas al final de la importación. Deje que se ocupe de corregir el error y reimportar si es importante.
  • Tenga una forma significativa de detectar las filas duplicadas que se analizan, ya que los valores de los campos clave son los mismos y la acción que se realizará con las filas duplicadas. (actualice el antiguo / descartar / pregunte al usuario qué hacer, etc.)

Añadiré más según me encuentre / recordaré más.

El mayor “gotcha” parece estar incluyendo la puntuación en los datos.
Por ejemplo, si mi registro es Nombre, Número de ID y escribo “Jerry”, 1,000
Se convertirán en tres campos en lugar de dos porque pongo la coma en el número. Ahora realmente lee “Jerry”, 1, 000 en lugar de “Jerry”, 1000
Si mi archivo CSV permite una selección de delimitadores, debería elegir los delimitadores que no interfieran con los datos. Entonces, si elijo una línea vertical (|) en lugar de una coma, mi registro sería “Jerry” | 1,000 y el 1,000 está bien.