Как да сравните съдържанието на две полета с форматиран текст и да маркирате символите, които са променени?

Кодът, който използвах за четене на съдържанието на 2 richtextbox, е както следва:

richTextBox1.Text = File.ReadAllText(tfsVersionFilePath);
richTextBox2.Text = File.ReadAllText(dbVersionFilePath);

Сега трябва да сравня съдържанието на двете полета с богат текст и да маркирам знаците, които са променени в двете полета с богат текст. Целта е да се получи разликата и да се маркират знаците as in TFS (сравняващи файлове) чрез c# приложение. Благодаря.

Редактиране:

int length = (richTextBox1.Text.Length > richTextBox2.Text.Length) ? richTextBox1.Text.Length : richTextBox2.Text.Length;
for (int i = 0; i < length; i++)
{ 
   if (richTextBox1.Text[i] != richTextBox2.Text[i])
   {
      /* and then start your highlight selection here, 
      this is where some difference between the two rich 
      text boxes begins */

      richTextBox1.Select(i, 1); 
      richTextBox1.SelectionColor = System.Drawing.Color.Yellow; 
      richTextBox1.SelectionBackColor = System.Drawing.Color.Red;
   }
}

Това, което разбрах от отстраняването на грешки, е, че методът Select или SelectionColor или SelectionBackColor на richTextBox1, насочващ текстовия курсор, се увеличава до 7 позиции след изпълнението на конкретните редове. Как да поддържам позицията на курсора на richTextBox1?


person John Stephen    schedule 22.07.2014    source източник
comment
маркирайте знаците, които са променени Как се променят знаците при сравняване?   -  person Suji    schedule 22.07.2014
comment
искате ли да проверите дума по дума или буква по буква?   -  person Suji    schedule 22.07.2014
comment
Най-новата версия в едно поле с богат текст и предишна версия в друго поле с богат текст. Както в TFS, дори ако 50 се промени на 60, тогава ще подчертае 5 и 6 и в двете версии. По същия начин, Sujith. Благодаря.   -  person John Stephen    schedule 22.07.2014
comment
добре тогава какъв ще бъде очакваният резултат?   -  person Suji    schedule 22.07.2014
comment
@SujithKarivelil, Очакван резултат в този момент, трябва да подчертая тези променени знаци and/or думи. Благодаря.   -  person John Stephen    schedule 22.07.2014
comment
тук искате да маркирате Последни и предишни, нали?   -  person Suji    schedule 22.07.2014
comment
@SujithKarivelil, Да, точно така.   -  person John Stephen    schedule 22.07.2014
comment
Разгледайте stackoverflow.com/questions/1509771/   -  person Kris Vandermotten    schedule 25.07.2014
comment
@KrisVandermotten, не мога да стартирам приложението от изходния код, предоставен в горната връзка diff.net. Хвърляйки много грешки, почти опитах изходния код да работи най-малко 3 часа. Но с приложението (инсталатора) в изтеглената папка, опитах и ​​ми даде очаквания резултат и показването на разликите беше добре. Сега не знам как да продължа, благодаря.   -  person John Stephen    schedule 25.07.2014


Отговори (3)


Първо похвала на ArtyomZzz за това, че посочи страхотния източник на DiffMatchPatch!

Ето част от кода, който ще нарисува променените знаци в две RichTextboxes при натискане на бутон.

Първо изтеглете diff-match-patchsource. (!Вижте актуализацията по-долу!) От zip файла копирайте 'DiffMatchPatch.cs' и също 'COPY' във вашия проект и включете cs файла във вашия проект. Също така добавете пространството от имена към клаузите си за използване.

using DiffMatchPatch;

namespace RTF_diff
{
  public partial class Form1 : Form
  {
    public Form1()
    {
        InitializeComponent();
    }

    // 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 RTBs:
    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 };


    public struct Chunk
    {
        public int startpos;
        public int length;
        public Color BackColor;
    }


    private void button1_Click(object sender, EventArgs e)
    {
        diffs = DIFF.diff_main(RTB1.Text, RTB2.Text);
        DIFF.diff_cleanupSemanticLossless(diffs);      // <--- see note !

        chunklist1 = collectChunks(RTB1);
        chunklist2 = collectChunks(RTB2);

        paintChunks(RTB1, chunklist1);
        paintChunks(RTB2, chunklist2);

        RTB1.SelectionLength = 0;
        RTB2.SelectionLength = 0;
    }


    List<Chunk> collectChunks(RichTextBox RTB)
    {
        RTB.Text = "";
        List<Chunk> chunkList = new List<Chunk>();
        foreach (Diff d in diffs)
        {
            if (RTB == RTB2 && d.operation == Operation.DELETE) continue;  // **
            if (RTB == RTB1 && 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 == RTB1 ? colors1[(int)d.operation]
                                       : colors2[(int)d.operation];
            chunkList.Add(ch);
        }
        return chunkList;

    }

    void paintChunks(RichTextBox RTB, List<Chunk> theChunks)
    {
        foreach (Chunk ch in theChunks)
        {
            RTB.Select(ch.startpos, ch.length);
            RTB.SelectionBackColor = ch.BackColor;
        }

    }

  }
}

Отначало се опитвах да оцветя променените линии като цяло в по-светъл цвят; това обаче изисква значително повече работа, не може да се направи (оцветяване на целия ред, а не само на частта със съдържание) и не беше част от въпроса ви на първо място..

Забележка: Има четири различни метода за почистване след разлика. Кое е най-подходящото ще зависи от входа и целта. Предлагам да опитате cleanupSemanticLossless. Добавих трета екранна снимка, показваща как работи това почистване

Ето екранна снимка на изхода: оригинален изход

И една от новите версии: нова екранна снимка

Екранна снимка след почистванеSemanticLossless: 3-та екранна снимка

Актуализация: Източниците изглежда са преместени. Това трябва да помогне..

person TaW    schedule 26.07.2014
comment
Благодаря Ви за отговора. Ще опитам вашето решение и ще ви актуализирам, след като завърша. Благодаря. - person John Stephen; 26.07.2014
comment
Екранната снимка по-горе в отговора ви има един и същ текст на richtextboxes и няма разлики. Така че не трябва да има подчертаване, но показва осветяването на някои текстове. Моля обяснете. Благодаря. - person John Stephen; 27.07.2014
comment
Също така какво е пространството от имена, което трябва да добавим за Chunk в List<Chunk> chunklist1; - person John Stephen; 27.07.2014
comment
Зелените части са добавени, червените части са пропуснати в сравнение с другия текст. в баланса това прави текстовете еднакви. Мислех, че ще е добре, но сега виждам, че един страничен ефект е, че човек не може да продължи да работи с текстовете, които сега са идентични. Натискането на бутона Diff два пъти премахва всички акценти. вън! Скоро ще адаптирам отговора си.. - person TaW; 27.07.2014
comment
използване на DiffMatchPatch; - person TaW; 27.07.2014
comment
Добре, ще чакам вашия актуализиран отговор. Благодаря. - person John Stephen; 27.07.2014
comment
Вече използвах DiffMatchPatch и мога да използвам Diff чрез това, но chunk иска препратка. Благодаря. - person John Stephen; 27.07.2014
comment
Добавени са два реда (**) за потискане на парчета, които всъщност не са в текста. Това прави цветовата схема излишна, тъй като нищо изтрито никога не се показва, разбира се.. Chunk е структура, дефинирана в кода. Добавихте ли DiffMatchPatch.cs към вашия проект? - person TaW; 27.07.2014
comment
comment
Опитах вашето актуализирано решение. Работеше добре, както се очакваше. Благодаря ви много за ценното време, прекарано с мен, и за страхотния отговор. Благодаря много. - person John Stephen; 27.07.2014
comment
Google Code изглежда адски бъгово: Всички файлове се премахват и дори някои връзки като _browse връщат грешки... - person Lion; 11.03.2017
comment
Хм, не съм сигурен за това: изглежда добре, но не съм тествал - person TaW; 11.03.2017
comment
съжалявам Последното изречение във вашия отговор гласи This or this should help... И двата this сочат към една и съща връзка. Печатна грешка ли е? - person Let Me Be Your Lost Disciple; 11.04.2018
comment
Хм, не помня съвсем, но си прав, и двете сочат към една и съща страница в github. ще изтрия едно.. - person TaW; 11.04.2018
comment
Казвате: Добавени са два реда ( ** ) за потискане на части, които всъщност не са в текста. .... По този начин се губи синхронизацията на линията, защото евентуалният нов ред ('\n') не се прилага. - person Caesar; 21.07.2018
comment
за c# wpf, как да заменя свойството rtb.selectionlength, rtb.textlength, rtb.select и rtb.selectonbackcolor? - person ; 27.11.2019
comment
@John: Не правя WPF. Трябва да проучите документи и/или потърсете урок; има няколко там.. - person TaW; 27.11.2019
comment
Някой има ли пример за това с помощта на VB.Net? - person Michael Harmon; 14.06.2021

Доколкото разбирам проблемът е:

  • сравнете 2 файла
  • показва разликите във файловете в приложението .net.

Най-лесният начин е да използвате https://github.com/curran/google-diff-match-patch (предишната връзка беше https://code.google.com/p/google-diff-match-patch/, благодарение на Паоло Коста за коментар)

Може да сравнява файлове (с няколко опции, които можете да зададете) и да формира Html вместо вас (с разлики). Също така можете да напишете своя собствена логика за извеждане (ако html не ви подхожда) - вижте метода DiffMatchPatch.diff_prettyHtml(...) (много е прост).

p.s.

if (richTextBox1.Text[i] != richTextBox2.Text[i])

не е "най-добрият" подход за сравнение на файлове. По-сложно е.

person Artyom    schedule 25.07.2014
comment
google diff Вече видях демонстрацията, която предоставиха. Той не показва разликите, докато TFS сравнява файловете и показва разликите по-долу. Освен това можете ли да ми предложите добър подход за сравнение на файлове. Благодаря. - person John Stephen; 25.07.2014
comment
Можете ли да предоставите 2 прости файла, които сравнявате, и екранна снимка на очаквания резултат? Не използвам TFS (само git), но мисля, че те са много сходни и google lib може да възпроизведе поведението на TFS. - person Artyom; 25.07.2014
comment
Благодаря ви за отговора и предложението да използвате google diff и получих очаквания резултат за показване на разликите и подчертаване, последвано от отговора на TaW. - person John Stephen; 27.07.2014

Просто мисля на глас тук, но друг начин да го направите би бил:

int length = (richTextBox1.Text.Length > richTextBox2.Text.Length) ? richTextBox1.Text.Length : richTextBox2.Text.Length;
for (int i = 0; i < length; i++)
{ 
   if (richTextBox1.Text[i] != richTextBox2.Text[i])
   {
      /* and then start your highlight selection here, 
      this is where some difference between the two rich 
      text boxes begins */
   }

Това ще премине през двете полета с богат текст едновременно и ще подчертае разликите. Звучи сякаш може да е повече от това, което търсите.

Използвайте връзката, която публикувах от другия си отговор, за да ви помогна заедно с малкото за подчертаване. Това малко парче код трябва да помогне при сравнението на текста.

person Michael Di Felice    schedule 22.07.2014
comment
Мога да получа разликата, но подчертаването работи погрешно. (т.е.) седем знака са увеличени и сочат. - person John Stephen; 23.07.2014
comment
@JohnStephen трябва да работи, можете ли да публикувате частта, която ви създава проблем? Може да е нещо просто, - person Michael Di Felice; 23.07.2014
comment
Кодът, който добавих, е в условието if, което беше както следва richTextBox1.Select(i, 1); richTextBox1.SelectionColor = System.Drawing.Color.Yellow; richTextBox1.SelectionBackColor = System.Drawing.Color.Red; - person John Stephen; 24.07.2014
comment
Това, което разбрах от отстраняването на грешки, е, че методът Select или SelectionColor или SelectionBackColor за richTextBox1 насочване на текстовия курсор се е увеличил до 7 позиции след изпълнението на конкретните редове. - person John Stephen; 24.07.2014
comment
Може да имате повече късмет със следния пример, като използвате маркер, за да определите началото на селекцията и след това преместите напред броя знаци, които остават различни, докато анализирате текста на richTextBox: stackoverflow.com/questions/14765947/ - person Michael Di Felice; 24.07.2014
comment
Препращам към връзката, но не мога да разбера какво да направя за моя проблем с тези отговори. Можете ли да предоставите актуализация в отговора си от тази връзка. Благодаря. - person John Stephen; 25.07.2014