Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

compare two text files using linq?

Tags:

c#

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; 
like image 780
bala3569 Avatar asked Dec 21 '10 12:12

bala3569


2 Answers

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;
like image 57
Jan Avatar answered Nov 18 '22 16:11

Jan


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!

like image 4
Matt Ellen Avatar answered Nov 18 '22 15:11

Matt Ellen