2010-10-21 23 views
6

Tengo un archivo de texto que contiene 21000 cadenas (una línea cada una) y 500 MB de otros archivos de texto (códigos fuente). Para cada cadena, necesito determinar si está contenida en cualquiera de esos archivos. Escribí un programa que hace el trabajo, pero su rendimiento es terrible (haría eso en un par de días, necesito hacer el trabajo en un máximo de 5-6 horas).
estoy escribiendo usando C#, Visual Studio 2010Búsqueda de múltiples cadenas en múltiples archivos

tengo par de preguntas acerca de mi problema:
a) ¿Qué método es mejor?

foreach(string s in StringsToSearch) 
{ 
    //scan all files and break when string is found 
} 

o

foreach(string f in Files) 
{ 
    //search that file for each string that is not already found 
} 

b) ¿Es mejor para escanear una línea de archivos por línea

StreamReader r = new StreamReader(file); 
while(!r.EndOfStream) 
{ 
    string s = r.ReadLine(); 
    //... if(s.Contains(xxx)); 
} 

o

StreamReader r = new StreamReader(file); 
string s = r.ReadToEnd(); 
//if(s.Contains(xxx)); 

c) ¿Sería enhebrar mejorar el rendimiento y cómo ¿Para hacer eso?
d) ¿Hay algún software que pueda hacer eso para no tener que escribir mi propio código?

+0

tienes que escribir el programa? windows has foundtr built. Puede usar un bucle for que podría buscar estos otros archivos en paralelo –

+0

Definitivamente no es una respuesta correcta/completa, pero no carga todos los archivos (500MB!) para cada cadena. Una vez que tenga (parte de) el archivo en la memoria, realice todas sus acciones a continuación. – Bertvan

+0

Solicito cargar todo el archivo uno por uno, no 500 MB de archivos a la vez. – Ichibann

Respuesta

3

Quiere minimizar la E/S de archivos, por lo que su primera idea es muy mala, ya que estaría abriendo los 'otros' archivos hasta 21.000 veces. Desea usar algo basado en el segundo (a1). Y cuando esos otros archivos no sean demasiado grandes, cárguelos en la memoria una vez con readAllText.

List<string> keys = ...; // load all strings 

foreach(string f in Files) 
{ 
    //search for each string that is not already found 
    string text = System.IO.File.ReadAllText(f); //easy version of ReadToEnd 


    // brute force 
    foreach(string key in keyes) 
    { 
     if (text.IndexOf(key) >= 0) .... 
    } 

} 

La parte de fuerza bruta se puede mejorar, pero creo que la encontrará aceptable.

+0

Is if (text.IndexOf (key)> = 0) más rápido que if (text.Contains (key))? – Ichibann

+0

@Ichi: No, espero que sean igual de rápidos. –

2
  1. Tanto en a) yb), segunda opción es eficiente
  2. roscado no puede mejorar el rendimiento coz cada hilo leería el archivo desde su disco, por lo que su disco se convertirá en un cuello de botella.
  3. sry no tengo ni idea acerca de s/w para su propósito

fragmento hilo

 foreach (FileInfo file in FileList) 
     { 
     Thread t = new Thread(new ParameterizedThreadStart(ProcessFileData)); 
     t.Start(file.FullName); 
     }//where processFileData is the method that process the files 

Directrices Generales de E/S

Lo que sigue son algunas recomendaciones básicas para reducir el La actividad de E/S de su programa y, por lo tanto, mejora su rendimiento. Al igual que con todas las recomendaciones, es importante medir el rendimiento del código optimizado antes y después de la optimización para garantizar que realmente sea más rápido.

  1. minimizar el número de archivo operaciones que realiza
  2. Grupo varias transferencias pequeña de E/S en una transferencia de gran tamaño.Una sola escritura de ocho páginas es más rápida que ocho escrituras separadas de una sola página, principalmente porque permite que el disco duro escriba los datos en una sola pasada sobre la superficie del disco. Para obtener más información sobre ,
  3. Realice lecturas secuenciales en lugar de buscando y leyendo bloques pequeños de datos . El kernel transparente agrupa las operaciones de E/S, lo que hace que las lecturas secuenciales sean mucho más rápidas.
  4. Evite saltar adelante en un archivo vacío antes de escribir datos. El sistema debe escribir ceros en el espacio intermedio para llenar el espacio. Para obtener más información, consulte Lectura es generalmente más barato que escribir de datos.
  5. Deferir cualquier operación de E/S hasta el punto que su aplicación realmente necesita los datos.
  6. utilizar el sistema de preferencias a capturar sólo las preferencias del usuario (tales como posiciones de las ventanas y vista ajustes) y no de datos que pueden ser recalculado económica.
  7. No suponga que almacenar en caché los datos del archivo en la memoria acelerará su aplicación . El almacenamiento de datos de archivos en la memoria mejora la velocidad hasta que la memoria se canjea en el disco, en cuyo punto paga el precio por accediendo nuevamente al disco. se esfuerzan por encontrar un equilibrio adecuado entre la lectura desde el disco y el almacenamiento en caché en la memoria
6

Si se acaba de querer saber si la cadena se encuentra o no se encuentra, y no necesitan ningún proceso ulterior, entonces te sugiero que solo uses grep. Grep es extremadamente rápido y está diseñado para este tipo de problema.

grep -f strings-file other-files... 

deberían hacer el truco. Estoy seguro de que hay una implementación de Windows en alguna parte. En el peor de los casos, Cygwin lo tendrá.

EDIT: Esto responde a la pregunta d)

+0

Sí, a pesar de la etiqueta [C#] este podría ser el mejor enfoque. –

+0

No estoy familiarizado con grep y cómo funciona, así que tal vez sea de poca ayuda cómo usarlo. – Ichibann

+0

Grep es una herramienta muy común en los sistemas * nix. Hay mucha documentación por ahí, por lo que seguramente habrá un buen tutorial en alguna parte. El comando sugerido busca todas las cadenas que se encuentran en "strings-file" en cualquiera de los "otros archivos" e imprime todas las líneas coincidentes en "otros archivos". Hay muchas opciones para cambiar el resultado a lo que necesita. –

2

¿La búsqueda tiene que ser en tiempo real de 500 MB actual de texto? La razón por la que pregunto es porque podría crear un índice de búsqueda en los archivos de texto y realizar búsquedas. Sería mucho más rápido ... Tome un vistazo a Lucene

Lucene.Net

C# and Lucene to index and search

+0

No necesita ser una búsqueda en tiempo real. Es una tarea de una sola vez. Hazlo y olvídate de él: P – Ichibann

+0

Luego usa Lucene (no he usado Windows Search SDK) para crear un índice de búsqueda completo y realizar búsquedas en su contra ... Utilicé Lucene antes ... ¡Es rápido! – zam6ak

Cuestiones relacionadas