La mejor manera de manejar archivos delimitados

16

Por lo general, un archivo CSV usa una coma y el carácter de retorno como delimitadores de campo y línea.

Esto se encuentra con problemas obvios con el texto que puede contener estos dos caracteres.

Obviamente hay opciones allí (escapar de ellas), pero ¿cómo manejan las personas esto? Usa diferentes personajes: ¿pipas o tildas? Escapar de ellos? ¿No usar archivos delimitados, después de todo es 2010 y tenemos XML ahora?

Buscando al menos esfuerzo para una oportunidad decente de no ver problemas.

(Solo para ser claros, esta es una pregunta por curiosidad en lugar de algo más sólido: es algo con lo que me he enfrentado una y otra vez jugando con datos, siempre lo superamos, pero normalmente se siente un poco, bueno, sucio, y se preguntó cuál era la experiencia de otras personas).

Jon Hopkins
fuente
Piense cuidadosamente sobre el uso de CSV: es agradable y fácil de manejar (vea las respuestas para las reglas de escape comunes), pero no es tan interoperable como debería ser: si solo se está comunicando con sus propios programas, está bien, pero si querer importar en otro lugar se vuelve un poco extraño porque diferentes programas obedecen a diferentes reglas de escape.
Michael Kohne
@ Michael - Absolutamente. Sin embargo, el problema es que es tan omnipresente que casi siempre encontrarás momentos en que es una opción muy tentadora, y en el caso de muchos sistemas más antiguos es la única opción.
Jon Hopkins
Las bibliotecas maduras existen en muchos idiomas (ciertamente los más comunes) para leer y escribir archivos delimitados por caracteres. Manejarán casi cualquier situación. Escribir el propio analizador CSV parece ser un tipo común de antipatrón.
quentin-starin

Respuestas:

13

De acuerdo con Wikipedia :

Los campos con comas incrustadas deben estar encerrados entre comillas dobles.

Y además:

Los campos con caracteres de comillas dobles deben estar encerrados dentro de los caracteres de comillas dobles, y cada uno de los caracteres de comillas dobles debe estar representado por un par de caracteres de comillas dobles.

No sé quién inventó eso, pero efectivamente muestra que eventualmente tienes que escapar. Es la única solución sólida. Todo lo demás es solo cinta adhesiva en la parte superior de la cinta adhesiva: tal vez funcione por ahora, pero eventualmente se topará con un caso en el que necesita una excepción a la excepción de una excepción, y no pasará mucho tiempo antes de que su bola de barro de reglas es mucho más complejo de lo que había sido una solución simple de caracteres de escape.

Parece que los creadores de CSV primero intentaron evitar las comas escapando con una sintaxis especial entre comillas dobles, que permitía guardar comas, pero luego alguien también quería guardar los caracteres de comillas dobles, por lo que tuvieron que escapar en ese momento, usando el comillas dobles como personaje de escape. Si hubieran decidido escapar adecuadamente en primer lugar, la sintaxis sería más simple ahora.

Joonas Pulakka
fuente
3
Qué debería ser y qué es ... a menudo difiere :)
Tim Post
Creo que la solución está bastante bien. Para datos simples, CSV funciona bien, para datos complejos, entonces es necesario citar y escapar "con" "rastros de regreso a BASIC.
Ernelli
1
@Ernelli: Ahora que lo pienso más, en realidad puede ser un compromiso razonable entre la legibilidad humana y la simplicidad. El problema para escapar es que se ve feo para los humanos , a pesar de que es trivial que la computadora analice. Por lo tanto, reservar escapes solo para casos raros ("campos con caracteres de comillas dobles incrustados") produce una salida que generalmente parece bastante legible para los humanos. Esta es una buena solución, suponiendo que las comas en los nombres de campo se usan con más frecuencia que las comillas dobles en los nombres de campo.
Joonas Pulakka
2

Asumo que tienes algo como esto:

Foo,Baz,,,"Foo,Baz"

Si las cadenas que contienen el delimitador no se citan o escapan, no tiene una forma realmente confiable de analizar el archivo.

Sin embargo, puede examinar los datos para analizar y sacar conclusiones como:

  • Los flotadores separados por comas deben tratarse como una cadena
  • Si la línea anterior o posterior contiene menos delimitadores, omita el análisis de esta línea y regístrela
  • Tratar como "

Tienes que escribir un analizador para manejar cosas así, pero no tiene que ser complicado.

En mi experiencia, importar volcados masivos de algo como Excel siempre da como resultado tener que regresar y revisar algunas cosas raras. Su reto es dar a su programa justo el suficiente sentido común con respecto a los datos de modo que no hace un inserto loco. Luego revise lo que se registró y lave / enjuague / repita.

Una vez manejé un FAQ interno para una pequeña empresa que usaba todas las estaciones de trabajo de Ubuntu. Una parte de las preguntas frecuentes dio 'accesos directos de shell', y vino a mí tubería delimitada. Bueno, las respuestas también estaban típicamente delimitadas por tuberías (es decir, grep foo | algo) y no citadas ni escapadas. Siento ese dolor :)

Tim Post
fuente
2

No hay nada malo con CSV hasta cierto punto

CSV funciona bien para datos rígidamente definidos que es poco probable que cambien de formato y no generen muchas sorpresas en el analizador de destinatarios.

Aquí hay una lista práctica de las grandes trampas:

  1. Escapar "" s dentro de "" s (el campo contiene delimitador de campo)
  2. "" que contiene CRLF (el campo contiene delimitador de línea)
  3. Unicode (el formato de texto subyacente puede ser insuficiente)
  4. Diferentes terminadores de línea para diferentes sistemas operativos (¿CR o CRLF o LF o NUL?)
  5. Comentarios en línea (línea con el prefijo #, //, -,; etc.)
  6. Gestión de versiones (la última versión del archivo contiene más o menos campos)
  7. Diferenciar entre datos NULL y vacíos (, "", está vacío pero ,, ¿es nulo?)

Puede abordar esto con un encabezado de metadatos que describe cómo deben analizarse los campos, pero también puede usar XML. Es debido a este tipo de desastre CSV de forma libre que se inventó. El enfoque XML parece demasiado pesado para lo que, a primera vista, podría ser un problema simple.

Una alternativa popular es la estrategia del "delimitador de caracteres extraños". Esto evita muchos de los problemas de escape anteriores porque usa algo como un | (canalización) para delimitación de campos y un CRLF para la terminación de registros. Esto no soluciona el problema del campo de varias líneas (a menos que use un contador de campo), pero obtiene líneas bien formateadas para humanos.

En general, si solo está buscando una forma simple de manejar este tipo de archivo, en el mundo de Java, simplemente podría lanzar OpenCSV . De esa manera, abstrae todos los problemas en un marco establecido.

Gary Rowe
fuente
2

CSV sigue siendo un formato válido en muchas situaciones, especialmente porque todavía tiene que ser la forma más fácil para que un cliente escriba datos que deben importarse a su aplicación. A pocos de nuestros clientes les gusta tratar con XML, quizás porque es muy detallado y tiene todos esos paréntesis angulares "aterradores". Es mucho más simple para ellos envolver sus cerebros alrededor de una lista simple de elementos separados por un carácter acordado, y también de acuerdo en que el mismo carácter no será permitido en el contenido de un campo.

Dicho esto, aún debe manejar la entrada correctamente y verificar las situaciones en las que usan caracteres no válidos. Comencé a usar FileHelpers para mis necesidades de análisis CSV.

Dave
fuente
1

Normalmente sigo el estándar y escapo de ellos. En la mayoría de los lenguajes de programación hay un buen soporte incorporado o una buena biblioteca disponible.

depende de la situación qué formato se utilizará y CSV es un formato razonable para intercambiar estructuras de formato de datos simples.

Salandur
fuente
0

Olvídate de CSV, usa JSON . Fácil de escribir, fácil de analizar. XML es tan 2005 .

usuario281377
fuente
66
y tiene el mismo problema cuando quiere usar un personaje que es parte del formato JSON (como {o,)
Salandur
Salandur: ¡Para nada! ¡Hay reglas exactas sobre cómo escapar! Pero {y, ni siquiera es necesario escapar, porque en el interior hay cuerdas, ¡no son ambiguas!
usuario281377
1
Bueno y bueno, pero no recuerdo que Excel tenga la función "Exportar a JSON" :) Hay momentos en los que tiene que analizar cosas extrañas, aunque solo sea para obtener un formato más agradable.
Tim Post
1
Y JSON es totalmente brillante para pasar alrededor de un millón de objetos de la misma forma. Oh espera.
Frank Shearar
1
JSON no ofrece ninguna mejora con respecto al CSV con respecto a esta pregunta y carece crucialmente de interoperabilidad con muchas aplicaciones (como se ha mencionado, no se puede importar ni exportar desde Office, SQL DB, etc.). JSON es ideal para operaciones internas y livianas del lado del cliente, pero XML es mucho mejor para pasar datos entre aplicaciones.
Dan Diplo
0

Por lo general, lo que me encuentro haciendo es obtener un TSV (valores separados por tabulaciones) en lugar de un archivo CSV, extraer el archivo en Emacs y ver cuál de los pocos caracteres poco comunes que NUNCA usa ($ generalmente es una buena opción por aquí), y luego convierto todas las pestañas a $.

A partir de ahí, se le puede decir a GNU AWK que use $ como separador de campo, y Bob es tu tío.

John R. Strohm
fuente