Estoy viendo mis opciones de análisis de archivos delimitados (por ejemplo, CSV, separadores de pestañas, etc.) basados en la pila MS en general, y .net específicamente. La única tecnología que excluyo es SSIS, porque ya sé que no satisfará mis necesidades.Opciones de análisis CSV con .NET
Así que mis opciones parecen ser:
- Regex.Split
- TextFieldParser
- OLEDB CSV Parser
Tengo dos criterios que deben cumplir. En primer lugar, dado el siguiente archivo que contiene dos filas lógicas de datos (y cinco filas físicos en total):
101, Bob, "Keeps his house ""clean"".
Needs to work on laundry."
102, Amy, "Brilliant.
Driven.
Diligent."
Los resultados analizados deben ceder dos lógicas "filas", que consta de tres cadenas (o columnas) cada uno . ¡La tercera cadena de fila/columna debe preservar las nuevas líneas! Dicho de otra manera, el analizador debe reconocer cuándo las líneas "continúan" en la siguiente fila física, debido al calificador de texto "no cerrado".
El segundo criterio es que el delimitador y el calificador de texto deben ser configurables, por archivo. Aquí hay dos secuencias, tomadas de diferentes archivos, que debo ser capaz de analizar:
var first = @"""This"",""Is,A,Record"",""That """"Cannot"""", they say,"","""",,""be"",rightly,""parsed"",at all";
var second = @"~This~|~Is|A|Record~|~ThatCannot~|~be~|~parsed~|at all";
Un análisis adecuado de cadena "primera" sería:
- Este
- es decir, una, registro
- que "no se puede", dicen,
- _
- _
- sea
- razón
- Analizada
- en absoluto
El '_' significa simplemente que un espacio en blanco fue capturado - No quiero que aparezca un guión bajo literal.
Se puede hacer una suposición importante sobre los archivos planos que se analizarán: habrá un número fijo de columnas por archivo.
Ahora para profundizar en las opciones técnicas.
expresiones regulares
En primer lugar, muchos comentan que los respondedores de expresiones regulares "no es el mejor camino" para lograr el objetivo.Yo, sin embargo, encontrar un commenter who offered an excellent CSV regex:
var regex = @",(?=(?:[^""]*""[^""]*"")*(?![^""]*""))";
var Regex.Split(first, regex).Dump();
Los resultados, aplicado a la cadena "primero", son absolutamente maravilloso:
- "Este"
- "Es decir, una, Record"
- "Eso "" no puede" "dicen,"
- ""
- _
- "b e"
- razón
- 'analizada'
- en absoluto
Sería bueno si las cotizaciones se limpiaron, pero se puede tratar fácilmente con eso como un paso posterior del proceso. De lo contrario, este enfoque se puede utilizar para analizar ambas cadenas de muestras "primero" y "segundo", siempre que la expresión regular se modifique para símbolos de tilde y de tubería en consecuencia. ¡Excelente!
Pero el problema real se relaciona con los criterios de varias líneas. Antes de que se pueda aplicar una expresión regular a una cadena, debo leer la "fila" lógica completa del archivo. Lamentablemente, no sé cuántas filas físicas leer para completar la fila lógica, a menos que tenga una máquina de expresiones regulares/estado.
Esto se convierte en un problema de "pollo y huevo". Mi mejor opción sería leer todo el archivo en la memoria como una cadena gigante y dejar que la expresión regular clasifique las líneas múltiples (no revisé si la expresión regular anterior podía manejar eso). Si tengo un archivo de 10 gigas, esto podría ser un poco precario.
Activa la siguiente opción.
TextFieldParser
Tres líneas de código hará que el problema con esta opción aparente:
var reader = new Microsoft.VisualBasic.FileIO.TextFieldParser(stream);
reader.Delimiters = new string[] { @"|" };
reader.HasFieldsEnclosedInQuotes = true;
La configuración delimitadores se ve bien. Sin embargo, el "HasFieldsEnclosedInQuotes" es "se acabó el juego". Me sorprende que los delimitadores sean arbitrariamente configurables, pero en cambio no tengo otra opción de calificador que no sean las citas. Recuerde, necesito configurabilidad sobre el calificador de texto. Entonces, de nuevo, a menos que alguien conozca un truco de configuración de TextFieldParser, se acabó el juego.
OLEDB
Un colega me dice que esta opción tiene dos defectos principales. En primer lugar, tiene un rendimiento terrible para archivos grandes (por ejemplo, 10 gigas). En segundo lugar, me dicen, adivina los tipos de datos de datos de entrada en lugar de permitirte especificarlos. No está bien.
AYUDA
así que me gustaría saber los hechos me dieron mal (si lo hay), y las otras opciones que me perdí. Tal vez alguien sepa una forma de jurado de TextFieldParser para usar un delimitador arbitrario. Y tal vez OLEDB ha resuelto los problemas establecidos (¿o quizás nunca los tuvo?).
¿Qué dices?
¿Has probado las opciones enumeradas en http://stackoverflow.com/questions/316649/csv-parsing? – TrueWill
Estoy de acuerdo con @ Appleman1234, Filehelpers debería ser todo lo que necesita – Kane
¿[Filehelpers] (http://www.filehelpers.com/) cumple con sus requisitos? – Appleman1234