2011-04-27 29 views
7

Para el procesamiento de registro, mi aplicación necesita leer archivos de texto línea por línea. Primero usé la función readLine() de BufferedReader pero leí en Internet que BufferedReader es lento al leer archivos.
Después me trató de usar FileInputStream junto con un FileChannel y MappedByteBuffer pero en este caso no hay ninguna función similar a readLine() por lo que la búsqueda Mi texto para un salto de línea y procesarla:Forma más rápida de leer el archivo de texto línea por línea en Java

try { 
     FileInputStream f = new FileInputStream(file); 
     FileChannel ch = f.getChannel(); 
     MappedByteBuffer mb = ch.map(FileChannel.MapMode.READ_ONLY, 0L, ch.size()); 
     byte[] bytes = new byte[1024]; 
     int i = 0; 
     while (mb.hasRemaining()) { 
      byte get = mb.get(); 
      if(get == '\n') { 
       if(ra.run(new String(bytes))) 
        cnt++; 
       for(int j = 0; j<=i; j++) 
        bytes[j] = 0; 
       i = 0; 
      } 
      else 
       bytes[i++] = get; 
     } 
    } catch(Exception ex) { 
     ex.printStackTrace(); 
    } 

Sé que esto probablemente no sea una buena manera de implementarlo, pero cuando acabo de leer el archivo de texto en bytes es 3 veces más rápido que usar BufferedReader pero llamar al new String(bytes) crea un nuevo String y hace que el programa sea aún más lento que cuando usas un BufferedReader.
Así que quería preguntar ¿cuál es la forma más rápida de leer un archivo de texto línea por línea? Algunos dicen que BufferedReader es la única solución a este problema.

P.S .: ra es una instancia de RunAutomaton de la biblioteca dk.brics.Automaton.

+1

¿BufferedReader es realmente demasiado lento para sus necesidades? Es probablemente una de las soluciones más limpias y más fáciles de mantener si debe codificar en Java. –

+0

Si 'BufferedReader' es realmente demasiado lento para su aplicación, debería pensar en no usar Java u otros lenguajes administrados ... _ (Pero dudo que este sea el caso) _ – ordag

+1

[Aaron] (http: // stackoverflow. com/users/460201/aaron) la respuesta está a punto de borrarse como una respuesta de solo un enlace, así que lo pondré aquí como un comentario: "Verifique [este enlace] (http://nadeausoftware.com/articles/ 2008/02/java_tip_how_read_files_quickly) out. Contiene la comparación de velocidad de varios métodos ". –

Respuesta

19

Tengo mucha duda de que BufferedReader va a causar una sobrecarga significativa. Agregar tu propio código es, al menos, tan ineficiente, y posiblemente también incorrecto.

Por ejemplo, en el código que ha indicado está llamando al new String(bytes), que siempre va a crear una cadena de 1024 bytes, usando la codificación predeterminada de la plataforma ... no es una buena idea. Claro, borras la matriz más tarde, pero tus cadenas aún contendrán un montón de caracteres '\ 0', lo que significa mucho espacio desperdiciado, aparte de cualquier otra cosa. Debe al menos restringir la parte de la matriz de bytes desde la que se está creando la cadena (lo que también significa que no necesita borrar la matriz después).

¿Has probado realmente intentado usando BufferedReader y lo encontraste demasiado lento? Por lo general, debe escribir el código más simple que cumpla con sus objetivos primero, y luego verifique si es lo suficientemente rápido ... especialmente si su única razón para no hacerlo es un recurso no especificado que "lee en Internet". ¿QUIERES que encuentre cientos de ejemplos de personas que lanzan sugerencias de rendimiento incorrectas? :)

Como alternativa, es posible que desee mirar Guava sobrecarga de Files.readLines() que tiene un LineProcessor.

+1

He probado BufferedReader y está funcionando bien, pero el requisito del programa es ser muy rápido, así que solo estoy tratando de averiguar qué solución es la más rápida y la mejor para mi implementación. – Yoni

+2

@Yoni: "realmente rápido" es un requisito bastante vago. ¿Tienes alguna evidencia de que sea 'BufferedReader' el cuello de botella en lugar de (mucho más probable) la velocidad del disco físico? –

+0

Si leo los mismos archivos en bytes, es 3 veces más rápido que usando 'BufferedReader'. La velocidad de mi disco duro es de aproximadamente 150mb/s mientras mi programa lee a 30mb/s. – Yoni

0

De acuerdo con la publicación this SO, es posible que también desee probar la clase Scanner.

2

Using plain BufferedReader I got 100+ MB/s. Es muy probable que la velocidad con la que puede leer los datos del disco sea su cuello de botella, por lo que la forma en que realice la lectura no hará mucha diferencia.

BufferedReader no es la única solución, pero es lo suficientemente rápido para el 99% de los casos de uso, entonces ¿por qué hacer las cosas más complicadas de lo que deberían ser?

0

tengo un bucle muy simple que lee aproximadamente 2000 líneas (50k bytes) desde un archivo en la tarjeta SD usando BufferedReader y las lee todas en aproximadamente 100mS en modo depuración en la pestaña galaxy 2. no está mal. A continuación os pongo un escáner en el bucle y el tiempo fue por las nubes (decenas de segundos), además de un montón de mensajes GC_CONCURANT

Scanner scanner = new Scanner(line); 
int eventType = scanner.nextInt(16); 

lo que al menos en mi caso el escáner que es el problema, supongo que necesito para escanear los Ints de otra manera, pero no tengo idea de por qué podría ser tan lento

Cuestiones relacionadas