2010-05-18 11 views
6

Para buscar una cadena en un archivo y escribir las líneas con cadena coincidente en otro archivo se tarda 15 - 20 minutos por un único archivo zip de 70 MB (estado comprimido). ¿Hay alguna forma de minimizarlo?Buscar una cadena en un archivo y escribir las líneas coincidentes a otro archivo en Java

mi código fuente:

conseguir las entradas del archivo Zip

zipFile = new ZipFile(source_file_name); 

entries = zipFile.entries(); 

while (entries.hasMoreElements()) 

{ ZipEntry entry = (ZipEntry)entries.nextElement(); 

if (entry.isDirectory()) 
{ 
continue; 
} 
searchString(Thread.currentThread(),entry.getName(), new BufferedInputStream (zipFile.getInputStream(entry)), Out_File, search_string, stats); } 

zipFile.close(); 

búsqueda de cadenas

public void searchString(Thread CThread, String Source_File, BufferedInputStream in, File outfile, String search, String stats) throws IOException 

{ 

    int count = 0; 
    int countw = 0; 
    int countl = 0; 
    String s; 
    String[] str; 
    BufferedReader br2 = new BufferedReader(new InputStreamReader(in)); 
    System.out.println(CThread.currentThread()); 

     while ((s = br2.readLine()) != null) 
     { 
      str = s.split(search); 
      count = str.length - 1; 
      countw += count; //word count 
      if (s.contains(search)) 
      { 
      countl++; //line count 
      WriteFile(CThread,s, outfile.toString(), search); 
      } 
     } 

    br2.close(); 
    in.close(); 


} 

-------------------------------------------------------------------------------- 

public void WriteFile(Thread CThread,String line, String out, String search) throws IOException 

{ 
    BufferedWriter bufferedWriter = null; 
    System.out.println("writre thread"+CThread.currentThread()); 
    bufferedWriter = new BufferedWriter(new FileWriter(out, true)); 
    bufferedWriter.write(line); 
    bufferedWriter.newLine(); 
    bufferedWriter.flush(); 
} 

Por favor, me ayudan. Realmente toma 40 minutos para 10 archivos usando hilos y 15-20 minutos para un solo archivo de 70MB después de ser comprimido. Cualquier forma de minimizar el tiempo.

+0

Usted es solamente usando un hilo ¿Querías usar varios? Además, ni siquiera está utilizando los vales countw, countl y count. Deshazte de tu llamada dividida. –

+0

Sí. Intenté usar varios hilos. Uno para cada archivo en una carpeta. Pero incluso para un solo archivo, este proceso lleva casi 20 minutos. Entonces quiero minimizar el tiempo. – Geeta

+0

También puede usar varios hilos en un solo archivo. FileChannel puede bloquear regiones del archivo para su procesamiento (ver http://java.sun.com/j2se/1.4.2/docs/api/java/nio/channels/FileChannel.html#lock%28long,%20long,% 20boolean% 29). –

Respuesta

3

No estoy seguro si el costo que está viendo proviene de operaciones de disco o de manipulaciones de cadena. Asumiré por ahora que el problema son las cadenas, puede verificarlo escribiendo un controlador de prueba que ejecute su código con la misma línea una y otra vez.

te puedo decir que split() va a ser muy caro en su caso, ya que se está produciendo cadenas que no es necesario y luego reciclarlos, creando muchos gastos. Es posible que desee aumentar la cantidad de espacio disponible para su JVM con -Xmx.

Si solo separa las palabras por la presencia de espacios en blanco, entonces lo haría mucho mejor utilizando un comparador de expresiones regulares que crea antes del ciclo y lo aplica a la cadena El número de coincidencias cuando se aplica a una cadena dada se tu conteo de palabras, y eso no debería crear una serie de cadenas (lo cual es muy inútil y que no usas). Verás en los JavaDocs que la división funciona a través de expresiones regulares; eso es cierto, pero dividir hace el paso adicional de crear cadenas separadas y ahí es donde podría estar su desperdicio.

También puede usar una expresión regular para buscar la coincidencia en lugar de contener, aunque eso puede no ser significativamente más rápido.

Puede hacer que las cosas sean paralelas mediante el uso de varios subprocesos. Sin embargo, si split() es la causa de su duelo, su problema es la sobrecarga y la falta de espacio en el montón, por lo que no se beneficiará necesariamente de ello.

De manera más general, si necesita hacer esto mucho, puede escribir un script en un lenguaje más "amigable" para la manipulación de cadenas. Un script de 10 líneas en Python puede hacer esto mucho más rápido.

+1

'split() va a ser muy costoso' +1 para eso –

0

Un problema aquí podría ser que dejes de leer cuando escribes. Probablemente usaría un hilo para leer y otro hilo para escribir el archivo. Como una optimización adicional, el hilo que escribe los resultados podría almacenarlos en la memoria y escribirlos en el archivo como un lote, digamos cada diez entradas o algo así.

En el hilo de escritura debe poner en cola las entradas entrantes antes de manipularlas.

Por supuesto, es posible que primero deba depurar dónde se gasta ese tiempo, si es el IO u otra cosa.

+0

" Como una optimización adicional, el hilo que escribe los resultados podría almacenarlos en la memoria "- Esto es exactamente lo que BufferedWriter ya hace internamente. – Adamski

+0

Sí, por supuesto, tienes razón. Eso fue más como un comentario general. – fish

4

Está volviendo a abrir el manejador de salida del archivo para cada línea que escriba.

Es probable que tenga un gran impacto en el rendimiento de, superando con creces otros problemas de rendimiento. En su lugar, recomendaría crear el BufferedWriteruna vez (por ejemplo, en la primera coincidencia) y luego mantenerlo abierto, escribir cada línea coincidente y luego cerrar el Writer al finalizar.

Además, elimine la llamada a flush(); no es necesario enjuagar cada línea ya que la llamada al Writer.close() vaciará automáticamente cualquier dato no escrito en el disco.

Finalmente, como nota al margen, su estilo de nombre de variable y método no sigue la convención de Java camel case; es posible que desee considerar cambiarlo.

1

wow, ¿qué haces en este método

WriteFile(CThread,s, outfile.toString(), search); 

cada vez que tiene la línea que contiene el texto, que está creando BufferedWriter(new FileWriter(out, true));

Basta con crear un BufferedWriter en su método de searchString y el uso que insertar líneas No es necesario abrir eso una y otra vez. Mejorará drásticamente el rendimiento.

0

Hay muchos posibles cuellos de botella en este código para que cualquiera pueda estar seguro de cuáles son los más importantes. Por lo tanto, debe perfilar la aplicación para determinar qué causa que sea lenta.

Armado con esa información, decida si el problema está en leer el archivo ZIP, ajustar la búsqueda o escribir las coincidencias en el archivo de salida.

(abrir y cerrar repetidamente el archivo de salida es una mala idea , pero si usted consigue solamente un pequeño número de búsqueda le pega no hará mucha diferencia en el rendimiento general.)

Cuestiones relacionadas