2011-02-01 21 views
10

Tengo que leer un archivo de texto grande (> 10 GB) en C++. Este es un archivo csv con líneas de longitud variable. cuando trato de leer línea por línea usando ifstream funciona pero lleva mucho tiempo, supongo que esto es porque cada vez que leo una línea, va al disco y lee, lo que lo hace muy lento.Lectura de texto grande de manera eficiente en C++

Hay una manera de leer en bufferes, por ejemplo, leer 250 MB de una vez (utilizando el método de lectura de ifstream) y luego obtener líneas de este búfer, veo muchos problemas con la solución como el buffer puede tener líneas incompletas, etc. ..

Hay una solución para esto en C++ que maneja todos estos casos, etc. ¿Hay alguna biblioteca de código abierto que pueda hacer esto, por ejemplo, impulsar etc.?

Nota: Me gustaría evitar c orzuelo archivo * punteros etc.

+1

La biblioteca estándar ya utiliza búferes. Lleva mucho tiempo porque el archivo es grande. Quizás estás haciendo otra cosa. Publica el código que usas, podemos comentar sobre eso. –

Respuesta

7

Trate de usar la función de archivo de memoria de Windows asignada. Las llamadas se almacenan en un búfer y se puede tratar un archivo como si fuera solo memoria. memory mapped files

+0

unix siempre tenía mmap() para esto ... – vrdhn

+0

A menos que el entorno sea 64b, será imposible mapear un archivo completo de 10 GB en una sola vista, por lo tanto, incluso con esta aproximación, los límites de la línea deben manejarse del mismo modo que con los almacenamientos intermedios . Dicho esto, depender del sistema operativo para manejar todas las E/S y el almacenamiento en búfer utilizando archivos mapeados en memoria sigue siendo interesante y ofrece un gran rendimiento. – Suma

3

IOstream ya utilizan los búferes como usted describe (aunque normalmente solo unos pocos kilobytes, no cientos de megabytes). Puede usar pubsetbuf para hacer que use un buffer más grande, pero no esperaría grandes ganancias. La mayor parte de la sobrecarga en IOstreams proviene de otras áreas (como el uso de funciones virtuales), no de la falta de almacenamiento en búfer.

Si usted está funcionando esto en Windows, es posible que pueda ganar un poco escribiendo su propio búfer de la secuencia, y tener que llamar CreateFile directamente, pasando (por ejemplo) o FILE_FLAG_SEQUENTIAL_SCANFILE_FLAG_NO_BUFFERING. Bajo las circunstancias, cualquiera de estos puede ayudar sustancialmente a su rendimiento.

3

Si quieres velocidad real, entonces vas a tener que dejar de leer líneas en std :: string, y comenzar a usar char* s en el búfer. Ya sea que lea ese búfer usando ifstream::read() o archivos mapeados en memoria es menos importante, aunque read() tiene la desventaja de que tiene N líneas completas y una incompleta en el búfer, y necesita reconocer eso (puede hacerlo fácilmente escaneando) el resto del búfer para '\ n' - quizás colocando un NUL después del búfer y usando strchr). También deberá copiar la línea parcial al inicio del búfer, leer el siguiente fragmento del archivo para que continúe desde ese punto y cambiar la cantidad máxima de caracteres leídos de manera que no se desborde el búfer. Si está nervioso acerca de FILE *, espero que se sienta cómodo con const char * ....

Como está proponiendo esto por motivos de rendimiento, espero que tenga un perfil para asegurarse de que no sea su extracción de campo CSV, etc. ese es el verdadero cuello de botella.

Cuestiones relacionadas