2011-02-03 22 views
6

Imagine que tengo un archivo de texto muy grande. El rendimiento realmente importa.¿cuál es la forma más rápida de escanear un archivo muy grande en Java?

Todo lo que quiero hacer es escanearlo para buscar una cierta cadena. Quizás quiero contar cuántos de esos tengo, pero realmente no es el punto.

El punto es: ¿cuál es la manera más rápida?

No me importa el mantenimiento, tiene que ser rápido.

Rápido es la clave.

+12

Entonces, ¿necesita ser rápido? – Joel

+1

@Joel: No estoy muy seguro de si eso es lo que quería decir. –

+2

Más importante aún: ¿necesita ser rápido una vez o necesita buscar la misma fuente varias veces (obviamente para diferentes cadenas)? –

Respuesta

16

Para un fuera de búsqueda utilizar un Scanner, como se sugiere here

Una técnica simple que bien podría ser considerablemente más rápido que indexOf() es utilizar un escáner, con el método findWithinHorizon() . Si utiliza un constructor que toma un objeto File, Scanner realizará internamente un FileChannel para leer el archivo. Y para la coincidencia de patrones terminará usando un algoritmo Boyer-Moore para una eficiente búsqueda de cadenas .

+0

Bonito atajo para obtener todo lo que sugerí sin implementarlo manualmente. –

+0

nota: esto puede terminar cargando todo el archivo en la memoria – Aarjav

0

Cualquiera que sean las especificaciones, la IO asignada a la memoria suele ser la respuesta.

Editar: según sus requisitos, podría intentar importar el archivo en una base de datos SQL y luego aprovechar las mejoras de rendimiento a través de JDBC.

Edit2: this thread en JavaRanch tiene algunas otras ideas, que implican FileChannel. Creo que podría ser exactamente lo que está buscando.

+4

¿Cómo demonios podría ayudar JDBC de alguna manera? ¿De qué "mejoras de rendimiento" estás hablando? –

+0

... y también el algoritmo BMH. – stepancheg

+0

¿De qué estás hablando? No JDBC. solo lectura de archivo mate – chacko

1

carga todo el archivo en la memoria y luego buscar en el uso de una cadena algoritmo de búsqueda tales como Knuth Morris Pratt.

Editar:
Un Google rápido muestra this cadena de búsqueda de la biblioteca que parece haber implementado algunos algoritmos de búsqueda de cadenas diferentes. Tenga en cuenta que nunca lo he usado, así que no puedo responderlo.

+0

Sí, pero para cargarlo en la memoria debe leerlo primero en el disco, a menos que necesite hacer más de una búsqueda (tal vez, el OP no especifique) debería analizar la transmisión. –

4

En primer lugar, use nio (FileChannel) en lugar de las clases java.io. En segundo lugar, utilice un eficiente string search algorithm como Boyer-Moore.

Si necesita buscar repetidas veces por el mismo archivo para diferentes cadenas, querrá construir algún tipo de índice, así que eche un vistazo a Lucene.

+0

¿por qué nio en vez de io? las clases nio son para escalar, no necesariamente para velocidad. – jtahlborn

+0

@jtahlborn: Está confundiendo un aspecto (red escalable a través de selectores) para el conjunto. Las clases nio también pueden acelerar mucho las operaciones de archivos al evitar operaciones de copia. Por ejemplo (y relevante para esta pregunta), un MappedByteBuffer puede usar directamente los datos de la página del disco proporcionados por el sistema operativo, mientras que un BufferedInputStream tiene que copiarlo porque está construido en la parte superior de la interfaz InputStream. –

+0

para trabajar con los datos, aún tendrá que copiarlo en el montón de Java. entonces, para las operaciones que son leídas una sola vez a través del archivo, dudo que esto haga una diferencia significativa. – jtahlborn

0

Utilice la herramienta adecuada: completa biblioteca de búsqueda de texto

Mi sugerencia es hacer una (o índice de archivos basado en el almacenamiento en caché está habilitado) índice en la memoria y luego realizar la búsqueda en él. Como se sugirió @Michael Borgwardt, Lucene es la mejor biblioteca disponible.

0

No sé si esta es una sugerencia estúpida, pero grep no es una herramienta de búsqueda de archivos bastante eficiente? Tal vez puede llamarlo usando Runtime.getRuntime().exec(..)

0

Depende de si necesita hacer más de una búsqueda por archivo. Si necesita hacer solo una búsqueda, lea el archivo desde el disco y analícelo con las herramientas sugeridas por Michael Bogwart. Si necesita hacer más de una búsqueda, probablemente debería crear un índice del archivo con una herramienta como Lucene: lea el archivo, conviértalo en token, pegue los tokens en el índice. Si el índice es lo suficientemente pequeño, hágalo en la RAM (Lucene le da la opción de RAM o índice respaldado por disco). Si no, guárdelo en el disco.Y si es demasiado grande para RAM y está muy, muy, muy preocupado por la velocidad, almacene su índice en una unidad flash de estado sólido.

Cuestiones relacionadas