2011-01-27 28 views
6

Tengo un archivo CSV de 10GB que es esencialmente una gran matriz cuadrada. Estoy tratando de escribir una función que pueda acceder a una sola celda de la matriz de la manera más eficiente posible, es decir, la matriz [12345,20000].Acceso aleatorio CSV; C#

Dado su tamaño, obviamente no es posible cargar toda la matriz en una matriz 2D, de alguna manera debo leer los valores directamente desde el archivo.

He buscado en Google el acceso aleatorio de archivos utilizando FileStream.Seek, sin embargo, lamentablemente debido al redondeo variable, cada celda no tiene un ancho fijo. No me sería posible buscar un byte específico y saber qué celda estoy mirando por algún tipo de aritmética.

Consideré escanear el archivo y crear una tabla de búsqueda para el índice del primer byte de cada fila. De esta forma, si quisiera acceder a la matriz [12345,20000] buscaría el inicio de la fila 12345 y luego exploraré la línea, contando las comas hasta que llegue a la celda correcta.

Estoy a punto de probar esto, pero ¿alguien más ha tenido mejores ideas? Estoy seguro de que no sería la primera persona en tratar de lidiar con un archivo como este.

Saludos

Edit: Debo señalar que el archivo contiene una matriz muy escasa. Si el análisis del archivo CSV termina siendo demasiado lento, consideraría convertir el archivo a un formato de archivo más apropiado y más fácil de procesar. ¿Cuál es la mejor manera de almacenar una matriz dispersa?

Respuesta

3

He usado el lector CSV de Lumenworks para archivos CSV bastante grandes, puede valer la pena echar un vistazo rápido para ver qué tan rápido puede analizar su archivo.

Lumenworks CSV

+1

No veo cómo puede esto evitar tanto buscar como cargar todo en el ram. Es solo un lector secuencial. –

1

Índice-archivo sería lo mejor que podría hacer. Apuesto. Al tener un tamaño de fila desconocido, no hay forma de saltar directamente a la línea que no sea escanear el archivo o tener un índice.

La única pregunta es qué tan grande es su índice. Si es demasiado grande, puede reducirla indexando solo cada 5ª línea (por ejemplo) y escanear en un rango de 5 líneas.

3

Antes que nada, ¿cómo te gustaría referirte a una fila en particular? ¿Es el índice de la fila para que tenga otra tabla o algo que le ayude a saber qué fila le interesa? ¿o es por una identificación o algo?

Estas ideas vienen a la mente

  • Su enfoque
  • La búsqueda binaria. Suponiendo que tiene una longitud promedio (tamaño/filas), puede usar una búsqueda binaria para buscar una fila, suponiendo que haya un identificador en la fila ordenada, y que le diga si está dando o no.
  • ¡Llámalo a una base de datos! Por cierto, ¿qué te impide hacer eso? Incluso puede usar SQL Express, que es gratuito, y para superar el límite de tamaño, puede fragmento sus datos en múltiples bases de datos.
+0

* Cargando en una base de datos * ... que crearía un índice sobre eso :) –

+0

Me gusta la idea de la búsqueda binaria. Sin embargo, como dijiste, requeriría tener un rowid en cada fila de csv. –

+0

Curiosamente, la matriz se generó a partir de datos de una base de datos SQL. No creé el generador, y ahora tengo que lidiar con la salida. Estoy considerando volver a poner los datos en un tipo de datos más estructurado. ¿Debo usar MSSQL o un archivo binario? – user593062

0

No estoy de acuerdo con que no deba cargar el archivo en la memoria RAM, especialmente si utiliza un sistema operativo de 64 bits.

No debería ser un problema asignar una matriz de tamaño 12345x20000: eso es solo alrededor de 1.9 GB en doble precisión. Y, de hecho, incluso si el tamaño fuera más grande, aún recomendaría este enfoque en una plataforma de 64 bits (consulte "memoria virtual").

En segundo lugar, indicó que su matriz era escasa, por lo tanto, podría cargar en la memoria RAM pero usar una representación dispersa para ahorrar algo de memoria.

En conclusión, si su aplicación requiere mucho acceso a su matriz y el rendimiento es algo importante, ponerlo en RAM definitivamente sería mi enfoque favorito.

+0

Por supuesto, podrías hacer ese procesamiento y poner el resultado en un archivo en lugar de en la RAM, aún obtendrías una búsqueda de tiempo constante, pero sería más lento – Greg

0

Preprocesa el archivo para que los campos sean de ancho fijo. Entonces puedes hacer tu lectura aleatoria fácilmente.

Haciendo géneros similares en el pasado, debería poder escribir un código simple que lea el archivo de ancho variable 10G de un disco local y escriba un archivo de ancho fijo 10G en un disco local en unos pocos (~ 20) minutos. Si la inversión en tiempo de anticipación vale la pena depende de la cantidad de lecturas aleatorias que necesita hacer y la frecuencia con que cambia el archivo a leer.

0

¿Qué pasa si creó 12345 archivo separado que se leen con instancias Lazy. Cada archivo solo se leería si los datos fueran necesarios. Si los datos son completamente escasos, podría crear una estructura de datos con una propiedad IsEmpty bool.

¿Necesita acceder al mismo elemento una y otra vez o simplemente necesita leer cada elemento una vez?

Cuestiones relacionadas