bala3569
bala3569

Reputation: 11010

compare two text files using linq?

I have 4 text files in one folder and a pattern.txt to compare these text files..In pattern.txt i have

insert
update
delete
drop

I need to compare this text file with those four text files and if these patterns matches any line in that text files i have to write those lines in another log file...i had read those files using linq..i need to compare those files and write in a text file with line number..here is my code

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);
            }

EDIT I have already used c# to compare two text files but i need this in 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; 

Upvotes: 5

Views: 2574

Answers (2)

Matt Ellen
Matt Ellen

Reputation: 11612

Since I'm a linq enthusiast, and will sometimes use a tool when it's inappropriate (I agree with @juharr about using grep or something similar for this situation) here is a possible version for you.

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);
}

Then you'd write the output of this function to a file.

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

I've set append to true in the StreamWriter, because I assume you don't want to lose the contents of the file each time you run the programme.

It looks pretty inefficient (not tested that aspect), but it uses linq and lambdas up the wazoo!

Upvotes: 4

Jan
Jan

Reputation: 16048

There might be a simpler solution, but this is at least working if you really want to use 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);
}

Or if you want, you can combine that into one LINQ query (but thats not very readable i think):

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;

Upvotes: 4

Related Questions