none
Comparison of two text files inside RichTextBoxes in C#

    Question

  • hi friends,
    I am developing a Comparison tool in C#. can anyone give me any idea to start with the comparison.
     
    Task Details:
     
    I am using C#2008. I want to compare two text files and wherever the diffrences in both the files it should be highlighted.
     
    My work:
     
    I am creating a windows application in c# where I am having two RichtextBoxes. I have loaded the file1 in 1st and file2 in 2nd Rich Text Box. Now I want to highlight the differences in RTB2 whereever It finds difference in first.
     
    I have started with the comparison where 
    I am comparing line by line (1 line from RTB1 and 1 line from RTB2); but in this case my logic is being fail; because 
     
    1. If the number of lines differnces in both the files.
    2. If lines moved from its position to another inside the same file.
    3. If new lines inserted or deleted in 2nd RichTextBox; then it finds first difference
    and highlighting that line but after that it is not matching any lines i.e. highligting each line as a difference in both the files. because of different number of lines.
     
    NOTE : If anybody used Epsilon S/w.....then this s/w provides this type of functionality. here it is providing character by character comparison and currsor always stopped
    when find differences in both files and showing the message "Difference Found". when again start comparision(Ctri+F2) then againg it shows next difference. and so on.......
     

    I have searched over Internet but didn't find anything. There are some tools provided on internet but I can't use the tools because of some restriction ... so I have to develop my own. I have also searched for algorithm for this purpose but unable to find it.
     
    Can anybody give me basic idea about how to start with this thing..... Please help me in this issue.
     
    Thanks & Regards,
    Locket5

    Thursday, July 17, 2014 5:14 AM

Answers

All replies

  • Hi,

    There are some methods you can try:

    http://stackoverflow.com/questions/6903360/compare-two-documents-and-change-text-color

    http://softwareworks.wordpress.com/comparing-text-filesn/

    http://forums.asp.net/t/1857185.aspx?how+to+compare+text+files+and+highlight+the+different+lines+

    May be these can help you!

    Best Wishes!


    We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place. <br/> Click <a href="http://support.microsoft.com/common/survey.aspx?showpage=1&scid=sw%3Ben%3B3559&theme=tech"> HERE</a> to participate the survey.

    Monday, July 21, 2014 8:14 AM
    Moderator
  • Hello friends,

     I have developed Comparison tool in C#. I  have disgn my form using 2 richtextbox  like Inputrichtextbox and outputrichtextbox, first textbox contains 1000 lines of text and second one contains 12000 lines of text, for comparing this two richtextboxs and highlghting the text is working fine.But the problem here  is , the matched text is not displaying in the same line. If i wanted to see the matched text i need to scroll the second textbox  for checking the matching text , but it doesn't make sense. So can any one please help me out by initiating the idea how to display matched text in the same line in both textboxes.

    I have used "DiffMatchPatch" class in my code

    Thanks in advance,



    Wednesday, July 29, 2015 2:05 PM
  • Here is my code

    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Configuration;
    using System.Data;
    using System.Data.SqlClient;
    using System.Drawing;
    using System.IO;
    using System.Linq;
    using System.Text;
    using System.Windows.Forms;
    using DiffMatchPatch;
    using System.Runtime.InteropServices;

    namespace Automation_RPAY
    {
        public partial class CompareInputOutputFiles : Form
        {
            // this is the diff object;
            diff_match_patch DIFF = new diff_match_patch();
            // these are the diffs
            List<Diff> diffs;
            // chunks for formatting the two RichTextBoxess:
            List<Chunk> chunklist1;
            List<Chunk> chunklist2;
            // two color lists:
            Color[] colors1 = new Color[3] { Color.LightGreen, Color.LightSalmon, Color.White, };
            Color[] colors2 = new Color[3] { Color.LightSalmon, Color.LightGreen, Color.White };
            //Color[] colors1 = new Color[3] { Color.White, Color.LightSalmon, Color.LightGreen, };
            //Color[] colors2 = new Color[3] { Color.LightSalmon, Color.White, Color.LightGreen };


            public struct Chunk
            {
                public int startpos;
                public int length;
                public Color BackColor;
            }
            string directory = string.Empty;
            string selectedInputfolder = string.Empty, selectedOutputfolder = string.Empty;
            //scrollbar for two rtbs
            public enum ScrollBarType : uint
            {
                SbHorz = 0,
                SbVert = 1,
                SbCtl = 2,
                SbBoth = 3
            }
            public enum Message : uint
            {
                WM_VSCROLL = 0x0115
            }
            public enum ScrollBarCommands : uint
            {
                SB_THUMBPOSITION = 4
            }
            [DllImport("User32.dll")]
            public extern static int GetScrollPos(IntPtr hWnd, int nBar);
            [DllImport("User32.dll")]
            public extern static int SendMessage(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam);
            public CompareInputOutputFiles()
            {

                InitializeComponent();
                gettreeviewdata();
                ///numbering to the rtb
                numberLabel.Font = new Font(rtxtInputBox.Font.FontFamily,
                                         rtxtInputBox.Font.Size + 1.019f);
                LableOutNumbers.Font = new Font(rtxtOutPutBox.Font.FontFamily,
                                        rtxtOutPutBox.Font.Size + 1.019f);

                rtxtInputBox.VScroll += RtxtInputBox_VScroll;
                rtxtOutPutBox.VScroll += RtxtOutPutBox_VScroll;
            }

            private void RtxtOutPutBox_VScroll(object sender, EventArgs e)
            {
                int outd = rtxtOutPutBox.GetPositionFromCharIndex(0).Y %
                                     (rtxtOutPutBox.Font.Height + 1);
                LableOutNumbers.Location = new Point(0, outd);

                UpdateOutPutNumbers();
            }

            private void RtxtInputBox_VScroll(object sender, EventArgs e)
            {
                int nPos = GetScrollPos(rtxtInputBox.Handle, (int)ScrollBarType.SbVert);
                nPos <<= 16;
                uint wParam = (uint)ScrollBarCommands.SB_THUMBPOSITION | (uint)nPos;
                SendMessage(rtxtOutPutBox.Handle, (int)Message.WM_VSCROLL, new IntPtr(wParam), new IntPtr(0));

                updateNumberLabel();
                UpdateOutPutNumbers();
            }


            private void btnCompare_Click(object sender, EventArgs e)
            {
                try
                {

                    //int counter = CompareRichTextContents(rtxtInputBox, this.rtxtOutPutBox);
                    //for (int i = 0; i < counter; i++)
                    //    CompareRichTextContents(this.rtxtInputBox, this.rtxtOutPutBox);
                    //Test();

                    diffs = DIFF.diff_main(rtxtInputBox.Text, rtxtOutPutBox.Text);
                    DIFF.diff_cleanupSemanticLossless(diffs);      // <--- see note !

                    chunklist1 = collectChunks(rtxtInputBox);
                    chunklist2 = collectChunks(rtxtOutPutBox);

                    paintChunks(rtxtInputBox, chunklist1);
                    paintChunks(rtxtOutPutBox, chunklist2);

                    rtxtInputBox.SelectionLength = 0;
                    rtxtOutPutBox.SelectionLength = 0;
                    updateNumberLabel();
                    UpdateOutPutNumbers();
                }
                catch (Exception ex)
                {
                    Logger.Error(ex.ToString(), "Could not compare the text files ");
                }
            }
            List<Chunk> collectChunks(RichTextBox RTB)
            {
                RTB.Text = "";
                List<Chunk> chunkList = new List<Chunk>();
                foreach (Diff d in diffs)
                {
                    if (RTB == rtxtOutPutBox && d.operation == Operation.DELETE) continue;  // **
                    if (RTB == rtxtInputBox && d.operation == Operation.INSERT) continue;  // **

                    Chunk ch = new Chunk();
                    int length = RTB.TextLength;
                    RTB.AppendText(d.text);
                    ch.startpos = length;
                    ch.length = d.text.Length;
                    ch.BackColor = RTB == rtxtInputBox ? colors1[(int)d.operation] : colors2[(int)d.operation];
                    chunkList.Add(ch);
                }
                return chunkList;

            }
            /// <summary>
            /// Description : Coloring for the differentiate text 
            /// </summary>
            /// <param name="RTB"></param>
            /// <param name="theChunks"></param>
            void paintChunks(RichTextBox RTB, List<Chunk> theChunks)
            {
                foreach (Chunk ch in theChunks)
                {
                    RTB.Select(ch.startpos, ch.length);
                    RTB.SelectionBackColor = ch.BackColor;
                }

            }

            private void BuildTree(DirectoryInfo directoryInfo, TreeNodeCollection addInMe)
            {
                try
                {
                    TreeNode curNode = addInMe.Add(directoryInfo.Name);
                    foreach (FileInfo file in directoryInfo.GetFiles())
                    {
                        // String name = file.Name;
                        //long size = file.Length;
                        if (file.FullName.Contains(".sql"))
                        {
                            curNode.Nodes.Add(file.FullName, file.Name);
                        }
                    }
                    foreach (DirectoryInfo subdir in directoryInfo.GetDirectories())
                    {
                        BuildTree(subdir, curNode.Nodes);
                    }
                }
                catch (Exception ex)
                {
                    Logger.Error(ex.ToString(), "Could not bind the tree views ");
                }
            }
            /// <summary>
            /// Description : Getting the data from root place for binding tree views
            /// </summary>
            private void gettreeviewdata()
            {
                try
                {
                    treeViewInput.Nodes.Clear();
                    treeViewOutput.Nodes.Clear();
                    directory = @"C:\Users\Ramana.Bandla\Downloads\Automation\";  //rootfolder from where input and output files are selected 
                    DirectoryInfo directoryInfo = new DirectoryInfo(directory);
                    if (directoryInfo.Exists)
                    {
                        treeViewInput.AfterSelect += treeViewInput_AfterSelect;
                        treeViewOutput.AfterSelect += treeViewOutput_AfterSelect;
                        BuildTree(directoryInfo, treeViewInput.Nodes);
                        BuildTree(directoryInfo, treeViewOutput.Nodes);
                    }
                }
                catch (Exception ex)
                {
                    Logger.Error(ex.ToString(), "Could not get the file");
                }
            }
            /// <summary>
            /// Description : Binding inputrichtextbox by selection of input files in input tree view
            /// </summary>
            /// <param name="sender"></param>
            /// <param name="e"></param>
            private void treeViewInput_AfterSelect(object sender, TreeViewEventArgs e)
            {
                try
                {
                    if (!e.Node.Text.Equals(""))
                    {
                        selectedInputfolder = directory + treeViewInput.SelectedNode.Text;
                        using (StreamReader sr = new StreamReader(treeViewInput.SelectedNode.FullPath))
                        {
                            String line = sr.ReadToEnd();
                            rtxtInputBox.Text = line;
                        }
                    }
                }
                catch (Exception ex)
                {
                    Logger.Error(ex.ToString(), "Could not read the file");
                }

            }
            /// <summary>
            /// Description : Binding outputrichtextbox by selection of output files in output tree view
            /// </summary>
            /// <param name="sender"></param>
            /// <param name="e"></param>
            private void treeViewOutput_AfterSelect(object sender, TreeViewEventArgs e)
            {
                try
                {
                    if (!e.Node.Text.Equals(""))
                    {

                        selectedOutputfolder = directory + treeViewOutput.SelectedNode.Text;
                        using (StreamReader sr = new StreamReader(treeViewOutput.SelectedNode.FullPath))
                        {
                            String line = sr.ReadToEnd();
                            rtxtOutPutBox.Text = line;
                        }
                    }
                }
                catch (Exception ex)
                {
                    Logger.Error(ex.ToString(), "Could not read the file");
                }
            }

            ///numbering to the rich text boxes
            private void updateNumberLabel()
            {
                //move location of numberLabel for amount 
                //of pixels caused by scrollbar
                int d = rtxtInputBox.GetPositionFromCharIndex(0).Y %
                                          (rtxtInputBox.Font.Height + 1);
                numberLabel.Location = new Point(0, d);

                int outd = rtxtOutPutBox.GetPositionFromCharIndex(0).Y %
                                          (rtxtOutPutBox.Font.Height + 1);
                LableOutNumbers.Location = new Point(0, outd);
                //we get index of first visible char and 
                //number of first visible line
                Point pos = new Point(0, 0);
                int firstIndex = rtxtInputBox.GetCharIndexFromPosition(pos);
                int firstLine = rtxtInputBox.GetLineFromCharIndex(firstIndex);

                //now we get index of last visible char 
                //and number of last visible line
                pos.X = ClientRectangle.Width;
                pos.Y = ClientRectangle.Height;
                int lastIndex = rtxtInputBox.GetCharIndexFromPosition(pos);
                int lastLine = rtxtInputBox.GetLineFromCharIndex(lastIndex);

                //this is point position of last visible char, we'll 
                //use its Y value for calculating numberLabel size
                pos = rtxtInputBox.GetPositionFromCharIndex(lastIndex);

                //finally, renumber label
                numberLabel.Text = "";
                for (int i = firstLine; i <= lastLine + 1; i++)
                {
                    numberLabel.Text += i + 1 + "\n";
                }


            }
            private void UpdateOutPutNumbers()
            {
                ///outputtext
                Point outpos2 = new Point(0, 0);
                int outfirstIndex2 = rtxtOutPutBox.GetCharIndexFromPosition(outpos2);
                int outfirstLine2 = rtxtOutPutBox.GetLineFromCharIndex(outfirstIndex2);

                //now we get index of last visible char 
                //and number of last visible line
                outpos2.X = ClientRectangle.Width;
                outpos2.Y = ClientRectangle.Height;
                int outlastIndex2 = rtxtOutPutBox.GetCharIndexFromPosition(outpos2);
                int outlastLine2 = rtxtOutPutBox.GetLineFromCharIndex(outlastIndex2);

                //this is point position of last visible char, we'll 
                //use its Y value for calculating numberLabel size
                outpos2 = rtxtOutPutBox.GetPositionFromCharIndex(outlastLine2);

                //finally, renumber label
                LableOutNumbers.Text = "";
                for (int i = outfirstLine2; i <= outlastLine2 + 1; i++)
                {
                    LableOutNumbers.Text += i + 1 + "\n";
                }
            }
            private void Test()
            {
                //String[] test = rtxtInputBox.Text.Split(new[] { "" }, StringSplitOptions.RemoveEmptyEntries);
                //String[] test2 = rtxtOutPutBox.Text.Split(new[] { "" }, StringSplitOptions.RemoveEmptyEntries);
                //bool wordNotFound = false;
                //for (int i = 0; i < test.Length; i++)
                //    for (int j = 0; j < test2.Length; j++)
                //    {
                //        if (test[i].Equals(test2[j]))
                //        {
                //            wordNotFound = false;
                //            break;
                //        }
                //        else wordNotFound = true;
                //    }

                //if (wordNotFound) rtxtInputBox.BackColor = Color.Red;
                //else rtxtInputBox.BackColor = Color.Green;

                string[] targetLines = rtxtInputBox.Lines;
                string[] destLine = rtxtOutPutBox.Lines;
                List<string> result = targetLines.Except(destLine).ToList<string>();
                foreach (string str in result)
                {

                    int lineIndex = Array.IndexOf(targetLines, str);
                    int lineCount = 0;
                    for (int index = 0; index < lineIndex; index++)
                    {
                        lineCount += targetLines[index].Length;
                    }
                    rtxtInputBox.SelectionBackColor = Color.Yellow;
                    rtxtInputBox.SelectionColor = Color.Black;
                    rtxtInputBox.SelectionStart = lineCount;
                    rtxtInputBox.SelectionLength = str.Length;

                }
            }
            private int CompareRichTextContents(RichTextBox target, RichTextBox dest)
            {
                int counter = 0; string[] targetLines = target.Lines; string[] destLine = dest.Lines;
                List<string> result = targetLines.Except(destLine).ToList();
                foreach (string str in result)
                {

                    int lineIndex = Array.IndexOf(targetLines, str);
                    int lineCount = 0;
                    for (int index = 0; index < lineIndex; index++)
                    {
                        lineCount += targetLines[index].Length + 1;
                    }
                    target.SelectionBackColor = Color.Yellow;
                    target.SelectionColor = Color.Black;
                    // target.Select(lineCount, str.Length);
                    target.SelectionStart = lineCount;
                    target.SelectionLength = str.Length;
                    counter++;

                }
                return counter;
            }

        }
    }

    Wednesday, July 29, 2015 2:13 PM