2011-08-30 3 views
2

Là où je travaille, nous avons un fichier journal qui contient des lignes comme celle-ci:Recherche dans un fichier journal non ordonnée

Ce qui est à lire comme suit:

31 | année (4) | mois (4) | jour (2) | heure (2) | min (2) | 000000 | facilité (3) | badge (5) | 0001

Donc, il est censé être une ligne pour chaque enregistrement, mais arrive des choses comme ceci:

 
31201007192000000000161206930004 
31201007192001000000161353900004 
31201031201007192004000000161204690004 
31201007192004000000090140470004 
31201007192005000000090148140004 
3120100719200500031201007191515000000161597180001 
31201007191700000000161203490001 
31201007191700000000161203490001 
31201007191700000000161202830001 
31201007191700000000 

C'est parce que le logiciel qui est censé lire le fichier, parfois, il manque quelques-uns des dossiers de newests et le gars en charge copie les anciens enregistrements à la fin du fichier. Donc, fondamentalement, c'est comme ça à cause d'erreurs humaines.

Lorsqu'un enregistrement n'est pas enregistré dans le DB, je dois rechercher le fichier. Au début, je ne faisais qu'un cicle qui parcourait tous les enregistrements du fichier, mais c'est vraiment lent et les problèmes mentionnés plus haut le ralentissaient. L'approche que j'ai est en ce moment avec une expression régulière et il est comme ça:

//Starts Reader 
StreamReader reader = new StreamReader(path); 
string fileLine = reader.ReadLine(); 
while (!reader.EndOfStream) 
{ 
    //Regex Matcher 
    Regex rx = new Regex(@"31\d\d\d\d\d\d\d\d\d\d\d\d000000161\d\d\d\d\d0001"); 

    //Looks for all valid lines 
    MatchCollection matches = rx.Matches(fileLine); 

    //Compares each match against what we are looking for 
    foreach (Match m in matches) 
    { 
    string s = m.Value; 
    compareLine(date, badge, s); 
    } 

    reader.ReadLine(); 
} 
reader.Close(); //Closes reader 

Ma question est la suivante: Qu'est-ce qu'une bonne façon de chercher dans le fichier? Devrais-je commander/nettoyer d'abord?

+0

Est-ce une ligne de commande [ 'sort'] (http://en.wikipedia.org/wiki/Sort_ (Unix)) ce sera beaucoup plus rapide que tout ce que vous pouvez faire en C# –

Répondre

2

Vous seriez probablement mieux loti, procédez comme suit:

  • Parse chaque ligne dans un objet. Une structure devrait être appropriée pour ces lignes. Incluez un objet DateTime ainsi que d'autres champs connexes. Cela peut être fait facilement avec Regex si vous le nettoyez un peu. Utilisez des groupes de capture et des répéteurs. Pour une année, vous pouvez utiliser (\d{4}) pour obtenir 4 numéros en ligne, au lieu de \d\d\d\d. Créez un List<MyStruct> qui contient chaque ligne en tant qu'objet.
  • Utilisez LINQ pour effectuer une recherche dans la liste, par exemple:

    var searchResults = from eachEntry in MyList 
            where eachEntry.Date > DateTime.Now 
            and eachEntry.facility.Contains("003") 
            select eachEntry;

, ajoutez également cette ligne à votre Regex, il accélérer, si seulement quelques millisecondes:

MatchCollection matches = rx.Matches(fileLine, RegexOptions.Compiled); 
0

Si vous connaissez (à l'avance) quelle entrée vous recherchez, par ex. vous connaissez exactement la date, l'installation et le lot que vous recherchez, vous n'avez pas besoin d'analyser les données du tout. Il pourrait être plus rapide pour générer la chaîne attendue et effectuer une recherche de chaîne simple au lieu d'utiliser des expressions régulières:

string expectedValue = getExpectedValue(date, badge); 
// expectedValue = "31201007192000000000161206930004" 
foreach (string line in lines) 
{ 
    if (line.IndexOf(expectedValue) >= 0) 
    { 
      // record found 
    } 
} 

Si vous ne souhaitez wether le fichier contient votre identifiant ou non, vous pouvez lire le dossier complet dans un seule chaîne et recherche par

string completeFile = GetFileContents(file); 
if (completeFile.IndexOf(expectedValue) >= 0) 
{ 
    // record found 
}