Actualmente estoy escribiendo algo que necesita manejar archivos de texto muy grandes (algunos GiB por lo menos). Lo que se necesita aquí (y esto es fijo) es:¿Cómo lidiar con un archivo de texto muy grande?
- basadas en CSV, siguiendo el RFC 4180, con la excepción de la línea incrustado rompe
- acceso de lectura al azar a las líneas, aunque la mayoría línea por línea y cerca del final
- líneas al final
- (líneas cambiantes). Obviamente que las llamadas para el resto del archivo que ser reescrito, también es raro, por lo que no es particularmente importante en este momento
El tamaño del archivo prohíbe mantener por completo en la memoria (que tampoco es deseable, ya que cuando los cambios deben agregarse tan pronto como sea posible).
He pensado en utilizar una región mapeada en memoria como una ventana en el archivo que se mueve si se solicita una línea fuera de su rango. Por supuesto, en esa etapa todavía no tengo abstracción por encima del nivel de bytes. Para trabajar con los contenidos tengo un CharsetDecoder
que me da un CharBuffer
. Ahora el problema es que puedo tratar con líneas de texto probablemente bien en el CharBuffer
, pero también necesito saber el desplazamiento de bytes de esa línea dentro del archivo (para mantener un caché de índices y compensaciones de línea, así no tengo para escanear el archivo desde el principio nuevamente para encontrar una línea específica).
¿Hay alguna manera de asignar las compensaciones en un CharBuffer
para compensar en la coincidencia ByteBuffer
en absoluto? Obviamente, es trivial con ASCII o ISO-8859- *, menos con UTF-8 y con ISO 2022 o BOCU-1 las cosas se pondrían realmente feas (no es que realmente esperara las dos últimas, pero UTF-8 debería ser el predeterminado aquí - y aún plantea problemas).
Creo que podría simplemente convertir una porción de CharBuffer
en bytes de nuevo y usar la longitud. O funciona o tengo problemas con signos diacríticos, en cuyo caso probablemente podría ordenar el uso de NFC o NFD para asegurar que el texto siempre esté codificado de manera no ambigua.
Aún así, me pregunto si ese es incluso el camino a seguir aquí. ¿Hay mejores opciones?
ETA: algunas respuestas a preguntas comunes y sugerencias aquí:
Se trata de un almacenamiento de datos para corridas de simulación, la intención de ser una alternativa local pequeño-montarse a una base de datos en toda regla. También tenemos backends de bases de datos y se usan, pero para los casos en los que no están disponibles o no se aplican, queremos esto.
También apoyo solo un subconjunto de CSV (sin saltos de línea incrustados), pero está bien por ahora. Los puntos problemáticos aquí son más o menos que no puedo predecir cuánto durarán las líneas y, por lo tanto, necesito crear un mapa aproximado del archivo.
En cuanto a lo que describí anteriormente: El problema que estaba ponderando era que puedo determinar fácilmente el final de una línea en el nivel del personaje (U + 000D + U + 000A), pero no quería suponer que esto se ve como 0A 0D
en el nivel de bytes (que ya falla para UTF-16, por ejemplo, donde es 0D 00 0A 00
o 00 0D 00 0A
). Pensaba que podía hacer que la codificación de caracteres cambiara al no codificar los detalles de la codificación que uso actualmente. Pero creo que podría apegarme a UTF-8 e ingorar en todo lo demás. Sin embargo, se siente mal, de alguna manera.
parece reinvención de las páginas de memoria del búfer del servidor sql. ¿Es el escenario de trabajo o cualquier otra cosa lo que le impide usar una base de datos integrada? – Osw
Cualquiera que sea la solución real, deberá crear al menos un índice de línea parcial o, si tiene el control completo del archivo y su contenido, puede considerar el uso de longitudes de línea fija. – biziclop