2010-12-21 35 views
5

mam 4 pliki tekstowe w jednym folderze i pattern.txt porównać te teksty files..In pattern.txt mamporównać dwa pliki tekstowe przy użyciu linq?

insert 
update 
delete 
drop 

muszę porównać ten plik tekstowy z tych czterech plików tekstowych, a jeśli tych wzorców pasuje dowolny wiersz w tych plikach tekstowych muszę napisać te linie w innym pliku dziennika ... Czytałem te pliki przy użyciu linq..i muszę porównać te pliki i napisać w pliku tekstowym z numerem linii ... tutaj jest mój kod

var foldercontent = Directory.GetFiles(pathA) 
        .Select(filename => File.ReadAllText(filename)) 
        .Aggregate(new StringBuilder(), 
        (sb, s) => sb.Append(s).Append(Environment.NewLine), 
        sb => sb.ToString()); 

var pattern = File.ReadAllLines(pathB).Aggregate(new StringBuilder(), 
        (sb, s) => sb.Append(s).Append(Environment.NewLine), 
        sb => sb.ToString()); 

using (var dest = File.AppendText(Path.Combine(_logFolderPath, "log.txt"))) 
      { 
     //dest.WriteLine("LineNo : " + counter.ToString() + " : " + "" + line); 
      } 

EDYTOWANIE już używany C#, aby porównać dwa pliki tekstowe, ale muszę to w LINQ

while ((line = file.ReadLine()) != null) 
{ 
if (line.IndexOf(line2, StringComparison.CurrentCultureIgnoreCase) != -1) 
{ 
dest.WriteLine("LineNo : " + counter.ToString() + " : " + " " + line.TrimStart()); 
} 
counter++; 
} 
file.BaseStream.Seek(0, SeekOrigin.Begin); 
counter = 1; 
+0

Czy musisz przechowywać plik, z którego pochodzą dopasowane linie? –

+0

@Matt Ellen: Potrzebuję przechowywać dopasowane linie w innym pliku tekstowym – bala3569

+0

@ bala3569: Tak, ale w pliku logu, czy musisz przechowywać który inny plik pochodzi z dopasowanej linii? –

Odpowiedz

4

Nie może być prostsze rozwiązanie, ale jest to przynajmniej działa, jeśli naprawdę chcesz używać LINQ:

var foldercontent = Directory.GetFiles(pathA) 
        .Select(filename => new 
        { 
         Filename = filename, 
         Lines = File.ReadAllLines(filename) 
        }) 
        .SelectMany(file => file.Lines.Select((line, idx) => new 
        { 
         LineNumber = idx + 1, 
         Text = line, 
         FileName = file.Filename 
        })); 

var pattern = File.ReadAllLines(pathB); 

var result = from fileLine in foldercontent 
      where pattern.Any(p => fileLine.Text.IndexOf(p, StringComparison.CurrentCultureIgnoreCase) != -1) 
      select fileLine; 

foreach (var match in result) 
{ 
    System.Diagnostics.Debug.WriteLine("File: {0} LineNo: {1}: Text: {2}", match.FileName, match.LineNumber, match.Text); 
} 

lub jeśli chcesz, że można połączyć w jeden kwerendy LINQ (ale nie to jest to bardzo czytelny chyba):

var result = from fileLine in (Directory.GetFiles(pathA) 
        .Select(filename => new 
        { 
         Filename = filename, 
         Lines = File.ReadAllLines(filename) 
        }) 
        .SelectMany(file => file.Lines.Select((line, idx) => new 
        { 
         LineNumber = idx + 1, 
         Text = line, 
         FileName = file.Filename 
        }))) 
       where File.ReadAllLines(pathB).Any(p => fileLine.Text.IndexOf(p, StringComparison.CurrentCultureIgnoreCase) != -1) 
       select fileLine; 
+0

Jeśli dam to tak jak to oznacza, że ​​pisze n razy, jeśli istnieje n wyników var result1 = string.Join (",", result.Select (x => x.ToString()). ToArray()); foreach (var match w wyniku) {dest.WriteLine (result1);} – bala3569

+0

Nie rozumiem dokładnie, co masz na myśli. Moje zapytanie LINQ daje ci wszystkie pasujące wiersze wszystkich plików. Nie podwoisz linii. – Jan

+0

ya podaje poprawnie, ale pisze n razy dla n liczby dopasowań – bala3569

4

Ponieważ jestem entuzjastą LINQ, a czasami użyć narzędzia, kiedy to inappropria te (zgadzam się z @juharr na temat używania grep lub czegoś podobnego w tej sytuacji) tutaj jest możliwa wersja dla ciebie.

static IEnumerable<string> CreateMatchesLog(string patternFilePath, string pathToSearch) 
{ 
    string logTemplate = "File {0}, Line: {1}, Pattern: {2}"; 
    DirectoryInfo di = new DirectoryInfo(pathToSearch); 
    var patternlines = File.ReadAllLines(patternFilePath); 
    var fileslines = di.EnumerateFiles().Select(fi => File.ReadAllLines(fi.FullName).Select((line, i) => new {fi.FullName, line, i})); 

    return from filelines in fileslines 
      from pattern in patternlines 
      from fileline in filelines 
      where fileline.line.Contains(pattern) 
      select String.Format(logTemplate, fileline.FullName, fileline.i + 1, pattern); 
} 

Następnie należy zapisać wyjście tej funkcji do pliku.

using (StreamWriter sw = new StreamWriter("log.txt", true)) 
{ 
    foreach (var log in CreateMatchesLog("pattern.txt", @"c:\test")) 
    { 
     sw.WriteLine(log); 
    } 
} 

mam ustawione Dołącz do true w StreamWriter, bo zakładam, że nie chce stracić zawartość pliku przy każdym uruchomieniu programu.

Wygląda całkiem nieefektywnie (nie testowano tego aspektu), ale używa linq i lambdas up the wazoo!