Estoy buscando sugerencias sobre cómo manejar un archivo csv que se está creando, luego cargado por nuestros clientes, y que puede tener una coma en un valor, como el nombre de una empresa.
Algunas de las ideas que estamos viendo son: identificadores citados (valor "," valores "," etc.) o usando un | en lugar de una coma. El mayor problema es que tenemos que facilitarlo, o el cliente no lo hará.
Respuestas:
Como han dicho otros, debe escapar de los valores que incluyen comillas. Aquí hay un pequeño lector CSV en C♯ que admite valores entre comillas, incluidas las comillas incrustadas y los retornos de carro.
Por cierto, este es un código probado por unidad. Lo estoy publicando ahora porque esta pregunta parece surgir mucho y es posible que otros no quieran una biblioteca completa cuando lo hará un simple soporte de CSV.
Puede usarlo de la siguiente manera:
Aquí están las clases. Tenga en cuenta que también puede usar la
Csv.Escape
función para escribir CSV válido.fuente
Para 2017, csv está completamente especificado: RFC 4180.
Es una especificación muy común, y está completamente cubierta por muchas bibliotecas ( ejemplo ).
Simplemente use cualquier biblioteca csv fácilmente disponible , es decir RFC 4180.
En realidad, hay una especificación para el formato CSV y cómo manejar las comas:
http://tools.ietf.org/html/rfc4180
Entonces, para tener valores
foo
ybar,baz
hacer esto:Otro requisito importante a tener en cuenta (también de la especificación):
fuente
System.Globalization.CultureInfo.CurrentCulture.TextInfo.ListSeparator
.El formato CSV usa comas para separar valores, los valores que contienen retornos de carro, avances de línea, comas o comillas dobles están rodeados por comillas dobles. Los valores que contienen comillas dobles se citan y cada cita literal se escapa mediante una cita inmediatamente anterior: por ejemplo, los 3 valores:
se codificaría como:
Cualquier campo puede ser citado, pero sólo los campos que contienen comas, CR / NL, o las citas debe ser citado.
No existe un estándar real para el formato CSV, pero casi todas las aplicaciones siguen las convenciones documentadas aquí . El RFC que se mencionó en otra parte no es un estándar para CSV, es un RFC para usar CSV dentro de MIME y contiene algunas limitaciones no convencionales e innecesarias que lo hacen inútil fuera de MIME.
Un problema que muchos módulos CSV que he visto no tienen en cuenta es el hecho de que se pueden codificar varias líneas en un solo campo, lo que significa que no puede suponer que cada línea es un registro separado, tampoco debe permitir nuevas líneas en su datos o estar preparado para manejar esto.
fuente
Pon comillas dobles alrededor de las cadenas. Eso es generalmente lo que hace Excel .
Ala Eli
fuente
Puede poner comillas dobles alrededor de los campos. No me gusta este enfoque, ya que agrega otro carácter especial (la comilla doble). Simplemente defina un carácter de escape (generalmente barra invertida) y úselo donde necesite escapar de algo:
No tiene que intentar hacer coincidir las comillas, y tiene menos excepciones para analizar. Esto también simplifica su código.
fuente
Hay una biblioteca disponible a través de nuget para tratar prácticamente cualquier CSV (.net) bien formado - CsvHelper
Ejemplo para asignar a una clase:
Ejemplo para leer campos individuales:
Dejar que el cliente maneje el formato de archivo:
,
es el delimitador de campo estándar,"
es el valor estándar utilizado para escapar de los campos que contienen un delimitador, una comilla o un final de línea.Para usar (por ejemplo)
#
para campos y'
para escapar:Más documentación
fuente
CsvHelper
biblioteca para resolver el problema del OP.Como mencioné en mi comentario a la respuesta de Harpo, su solución es buena y funciona en la mayoría de los casos, sin embargo, en algunos escenarios cuando las comas están directamente adyacentes entre sí, no se divide en las comas.
Esto se debe a que la cadena Regex se comporta inesperadamente como una cadena vertabim. Para que este comportamiento sea correcto, todos los "caracteres en la cadena de expresiones regulares deben ser escapados manualmente sin usar el escape vertabim.
Es decir. La expresión regular debería ser esto usando escapes manuales:
",(?=(?:[^\"\"]*\"\"[^\"\"]*\"\")*(?![^\"\"]*\"\"))"
que se traduce en
",(?=(?:[^""]*""[^""]*"")*(?![^""]*""))"
Cuando se utiliza una cadena vertabim,
@",(?=(?:[^""]*""[^""]*"")*(?![^""]*""))"
se comporta de la siguiente manera, como puede ver si depura la expresión regular:En resumen, recomiendo la solución de harpo, ¡pero ten cuidado con este pequeño problema!
He incluido en CsvReader una pequeña opción a prueba de fallos para notificarle si se produce este error (si tiene un número de columnas previamente conocido):
Esto se puede inyectar a través del constructor:
fuente
[^""]
mismo que[^"]
? La duplicación de un carácter dentro de una especificación de clase de caracteres es redundante, ¿verdad?Agregue una referencia a Microsoft.VisualBasic (sí, dice VisualBasic pero también funciona en C #, recuerde que al final todo es IL).
Use la
Microsoft.VisualBasic.FileIO.TextFieldParser
clase para analizar el archivo CSV. Aquí está el código de muestra:fuente
parser.HasFieldsEnclosedInQuotes = true;
y el archivo de entrada debería encerrar los campos que contienen comas entre comillas según la especificación CSV: Excel ya lo hace.Puede usar "delimitadores" alternativos como ";" o "|" pero lo más simple podría ser simplemente citar lo que es compatible con la mayoría de las bibliotecas CSV (decentes) y la mayoría de las hojas de cálculo decentes.
Para obtener más información sobre delimitadores CSV y una especificación para un formato estándar para describir delimitadores y citar, consulte esta página web
fuente
En caso de que esté en un sistema * nix , tenga acceso
sed
y pueda haber una o más comas no deseadas solo en un campo específico de su CSV, puede usar la siguiente línea para encerrarlas"
como Sección RFC4180 2 propone:Dependiendo del campo en el que se encuentren las comas no deseadas, deberá modificar / ampliar los grupos de captura de la expresión regular (y la sustitución).
El ejemplo anterior incluirá el cuarto campo (de seis) entre comillas.
En combinación con la
--in-place
opción aplicar estos cambios directamente al archivo.Para "construir" la expresión regular correcta, hay un principio simple a seguir:
[^,]*,
y los pone todos juntos en un grupo de captura.(.*)
.,.*
y las pone todas juntas en un grupo de captura.Aquí hay una breve descripción de las diferentes expresiones regulares / sustituciones dependiendo del campo específico. Si no se da, la sustitución es
\1"\2"\3
.Si desea eliminar las comas no deseadas en
sed
lugar de encerrarlas entre comillas, consulte esta respuesta .fuente
Si tiene ganas de reinventar la rueda, lo siguiente puede funcionar para usted:
fuente
En Europa tenemos este problema antes que esta pregunta. En Europa usamos toda una coma para un punto decimal. Vea estos números a continuación:
Por lo tanto, no es posible usar el separador de coma para los archivos CSV. Por esa razón, los archivos CSV en Europa están separados por un punto y coma (
;
) .Programas como Microsoft Excel pueden leer archivos con un punto y coma y es posible cambiar de separador. Incluso podría usar una pestaña (
\t
) como separador. Vea esta respuesta del usuario de Supper .fuente
Si está interesado en un ejercicio más educativo sobre cómo analizar archivos en general (usando CSV como ejemplo), puede consultar este artículo de Julian Bucknall. Me gusta el artículo porque divide las cosas en problemas mucho más pequeños que son mucho menos insuperables. Primero crea una gramática, y una vez que tiene una buena gramática, es un proceso relativamente fácil y metódico para convertir la gramática en código.
El artículo usa C # y tiene un enlace en la parte inferior para descargar el código.
fuente
Aquí hay una pequeña solución ordenada:
En su lugar, puede usar un signo de número inferior griego (U + 0375)
Se ve así ͵
El uso de este método también le ahorra muchos recursos ...
fuente
Simplemente use SoftCircuits.CsvParser en NuGet. Manejará todos esos detalles por usted y manejará eficientemente archivos muy grandes. Y, si es necesario, incluso puede importar / exportar objetos asignando columnas a las propiedades del objeto. Además, mis pruebas mostraron que promedia casi 4 veces más rápido que el popular CsvHelper.
fuente
Como se trata de prácticas generales, comencemos por las reglas generales:
No use CSV, use XML con una biblioteca para leer y escribir el archivo xml.
Si debe usar CSV. Hágalo correctamente y use una biblioteca gratuita para analizar y almacenar los archivos CSV.
Para justificar 1), la mayoría de los analizadores CSV no son conscientes de la codificación, por lo que si no está tratando con US-ASCII, está solicitando problemas. Por ejemplo, Excel 2002 está almacenando el CSV en codificación local sin ninguna nota sobre la codificación. El estándar CSV no es ampliamente adoptado :(. Por otro lado, el estándar xml está bien adoptado y maneja las codificaciones bastante bien.
Para justificar 2), hay toneladas de analizadores csv para casi todo el lenguaje, por lo que no hay necesidad de reinventar la rueda, incluso si las soluciones parecen bastante simples.
Por nombrar algunos:
para python use build en el módulo csv
para perl verifique CPAN y Texto :: CSV
para php use construir en funciones fgetcsv / fputcsv
para java verifique la biblioteca SuperCVS
Realmente no hay necesidad de implementar esto a mano si no vas a analizarlo en un dispositivo incorporado.
fuente
Puede leer el archivo csv de esta manera.
Esto hace uso de divisiones y cuida los espacios.
fuente
Primero, preguntémonos: "¿Por qué sentimos la necesidad de manejar las comas de manera diferente para los archivos CSV?"
Para mí, la respuesta es: "Porque cuando exporto datos a un archivo CSV, las comas en un campo desaparecen y mi campo se separa en múltiples campos donde las comas aparecen en los datos originales". (Eso es porque la coma es el carácter separador de campo CSV).
Dependiendo de su situación, los punto y coma también se pueden usar como separadores de campo CSV.
Dados mis requisitos, puedo usar un carácter, por ejemplo, una comilla simple de bajo 9, que se parece a una coma.
Entonces, así es como puedes hacerlo en Go:
El segundo carácter con aspecto de coma en la función Reemplazar es el decimal 8218.
Tenga en cuenta que si tiene clientes que pueden tener lectores de texto de solo ascii, este carácter de décima 8218 no se verá como una coma. Si este es su caso, entonces recomendaría rodear el campo con la coma (o punto y coma) con comillas dobles según RFC 4128: https://tools.ietf.org/html/rfc4180
fuente
En general, codifico con URL los campos que pueden tener comas o caracteres especiales. Y luego descifrarlo cuando se está utilizando / muestra en cualquier medio visual.
(las comas se convierten en% 2C)
Cada idioma debe tener métodos para codificar URL y decodificar cadenas.
por ejemplo, en Java
Sé que esta es una solución muy general y podría no ser ideal para situaciones en las que el usuario quiere ver el contenido del archivo csv, manualmente.
fuente
Por lo general, hago esto en mis rutinas de análisis de archivos CSV. Suponga que la variable 'línea' es una línea dentro de un archivo CSV y todos los valores de las columnas están encerrados entre comillas dobles. Después de que se ejecuten las dos líneas siguientes, obtendrá columnas CSV en la colección 'valores'.
fuente
La solución más simple que he encontrado es la que usa LibreOffice:
"
por”
También puede usar el que usa Excel:
"
por""
Observe que otras personas recomendaron hacer solo el paso 2 anterior, pero eso no funciona con líneas donde a
"
está seguido de a,
, como en un CSV donde desea tener una sola columna con la cadenahello",world
, ya que el CSV leería:Que se interpreta como una fila con dos columnas:
hello
yworld"
fuente
hello",world
campo simplemente debería guardarse como"hello"",world"
, que se puede analizar 100% correctamente.fuente
Utilicé la biblioteca Csvreader pero al usarla obtuve datos al explotar desde la coma (,) en el valor de la columna.
Entonces, si desea insertar datos de archivo CSV que contengan una coma (,) en la mayoría de los valores de las columnas, puede usar la siguiente función. Enlace del autor => https://gist.github.com/jaywilliams/385876
fuente
Usé la biblioteca papaParse para analizar el archivo CSV y tener los pares clave-valor (clave / encabezado / primera fila del archivo CSV-valor).
Aquí hay un ejemplo que uso:
https://codesandbox.io/embed/llqmrp96pm
tiene un archivo dummy.csv para tener la demostración de análisis CSV.
Lo he usado en reactJS, aunque es fácil y sencillo de replicar en una aplicación escrita en cualquier idioma.
fuente
Un ejemplo podría ayudar a mostrar cómo se pueden mostrar comas en un archivo .csv. Cree un archivo de texto simple de la siguiente manera:
Guarde este archivo de texto como un archivo de texto con el sufijo ".csv" y ábralo con Excel 2000 desde Windows 10.
aa, bb, cc, d; d "En la presentación de la hoja de cálculo, la línea de abajo debe verse como la línea de arriba, excepto que la siguiente muestra una coma en lugar de un punto y coma entre las d". aa, bb, cc, "d, d", esto funciona incluso en Excel
aa, bb, cc, "d, d", esto funciona incluso en Excel 2000 aa, bb, cc, "d, d", esto funciona incluso en Excel 2000 aa, bb, cc, "d, d", esto funciona incluso en Excel 2000
aa, bb, cc, "d, d", esto falla en Excel 2000 debido al espacio anterior a la primera cita aa, bb, cc, "d, d", esto falla en Excel 2000 debido al espacio anterior a la primera cita aa, bb, cc, "d, d", esto falla en Excel 2000 debido al espacio debajo de la primera cita
aa, bb, cc, "d, d", esto funciona incluso en Excel 2000 incluso con espacios antes y después de la segunda cita. aa, bb, cc, "d, d", esto funciona incluso en Excel 2000 incluso con espacios antes y después de la segunda cita. aa, bb, cc, "d, d", esto funciona incluso en Excel 2000 incluso con espacios antes y después de la segunda cita.
Regla: si desea mostrar una coma en una celda (campo) de un archivo .csv: "Comience y finalice el campo con comillas dobles, pero evite los espacios en blanco antes de la primera cita"
fuente
Creo que la solución más fácil para este problema es hacer que el cliente abra el csv en Excel y luego ctrl + r para reemplazar todas las comas con el identificador que desee. Esto es muy fácil para el cliente y requiere solo un cambio en su código para leer el delimitador de su elección.
fuente
Use un carácter de tabulación (\ t) para separar los campos.
fuente