0

I'm trying to compare two different text files and write in a new file the lines which are different. What I have so far writes the differences between the two files, I'm wondering what I would need to add to the code so I can write the lines as well. For example:

text1:
 a
 bc
 d
 _
 f

text2:
 a
 bcd
 d
 e
 _

what would be outputted with my code is:

_
d
_
e
f

what I'd like is:

line 2: d
line 4: e
line 5: f

hopefully this makes sense, here is my code:

private void button_compare_Click(object sender, EventArgs e)
{

    String directory = @"C:\.......\";
    String[] linesA = File.ReadAllLines(Path.Combine(directory, "test1.txt"));
    String[] linesB = File.ReadAllLines(Path.Combine(directory, "test2.txt"));

    IEnumerable<String> onlyB = linesB.Except(linesA);

    File.WriteAllLines(Path.Combine(directory, "Result2.txt"), onlyB);
}

EDIT I figured out my initial issue thanks to the excellent people who responded below. Out of curiosity I wanted to take it a bit further.... Suppose random lines in each file differed by one word. ex: text1: line 3: hello how are you

text2: line 3: hi how are you

How would you do it such that the output file simply has the word that has been changed? eg

output file: line 3: hello

user8168414
  • 11
  • 1
  • 3
  • There are lots of variations on the theme of comparing files, including algorithms that find insertions and deletions of entire lines. In your case, where you seem to be concerned only with edits of lines, the problem is simpler, but still addressed by review of the available prior art. See marked duplicates for inspiration and algorithms which can be applied to your scenario. – Peter Duniho Jun 28 '17 at 00:25

2 Answers2

1

You can't do this with except, as it returns the diffs only disregarding the line index. You have to iterate the lines.

 private void button_compare_Click(object sender, EventArgs e)
 {
       String directory = @"C:\.......\";
       String[] linesA = File.ReadAllLines(Path.Combine(directory, "test1.txt"));
       String[] linesB = File.ReadAllLines(Path.Combine(directory, "test2.txt"));

       List<string> onlyB = new List<string>();
    //previously, it was omitting the last line because of '<' so changed it to '<='
       for (int i = 0; i <= linesA.Length; i++)
       {
          if (!linesA[i].Equals(linesB[i])) 
          {
             onlyB.Add("line " + i + ": " + string.Join(" ",linesB[i].Split(' ').Except(linesA[i].Split(' '))));
          }
       }

       File.WriteAllLines(Path.Combine(directory, "Result2.txt"), onlyB);
  }
Amee Sami
  • 3
  • 2
igorc
  • 2,024
  • 2
  • 17
  • 29
  • Amazing! Thank you so much! Suppose random lines in each file differed by one word. ex: `text1: line 3: hello how are you` `text2: line 3: hi how are you` Would it be possible to have it such that the output file simply has the word that has been changed? eg `output file: line 3: hello` – user8168414 Jun 27 '17 at 21:37
  • edited the answer. – igorc Jun 27 '17 at 22:05
  • Cool, one thing I noticed when I tried your code was that the result.txt file is omitting the last line of text1 and text2 . Would you happen to know what the error is? – user8168414 Jun 27 '17 at 22:33
  • This will break (index out of range) when `linesB` is shorter than `linesA`. Also it ignores *extra* lines in B – Hans Kesting Jun 05 '20 at 08:35
0

I would just iterate through the collection and remove the '_' entries.

for (int i = 0; i < onlyB.Count(); i++) // go through every element in the collection
{
    string line = onlyB.ElementAt(i); // get the current element at index i
    if (line == "_") continue; // if the element is a '_', ignore it

    // write to the console, or however you want to output.
    Console.WriteLine(string.Format("line {0}: {1}", i, line));
}
Ian H.
  • 3,840
  • 4
  • 30
  • 60