Сравнение документов

Сравнение документов

Сравнение документов

Это руководство показывает, как сравнить два варианта текста и получить последовательность правок между ними, используя движок Aspose.PDF FOSS text-diff для .NET. Точка входа для этой модели сравнения — DiffOperation, одиночная правка, помеченная Operation (Equal, Delete, или Insert), совместно с DiffUtils вспомогательный класс для поиска общего текста и восстановления диффа обратно в исходный и целевой текст. Отдельный проход оптимизации, описанный в Оптимизация диффа, канонизирует необработанный вывод диффа, полученный таким способом, прежде чем он будет отрисован или применён.


Модель диффа: Операция и DiffOperation

Operation — это перечисление, которое классифицирует каждую правку в диффе: Equal обозначает участок текста, который не изменён, Delete обозначает участок, удалённый из исходного, а Insert обозначает участок, добавленный в целевой. DiffOperation связывает значение Operation с Text, к которому оно применяется, и реализует IEquatable<DiffOperation>, чтобы две правки можно было сравнить на равенство.

using Aspose.Pdf.Comparison.Diff;

// A single edit consists of an Operation and the run of text it applies to.
var unchanged = new DiffOperation(Operation.Equal, "Aspose.PDF ");
var removed = new DiffOperation(Operation.Delete, "for .NET Framework");
var added = new DiffOperation(Operation.Insert, "FOSS for .NET");

Console.WriteLine(unchanged.Operation); // Equal
Console.WriteLine(added.Text);          // "FOSS for .NET"

Поиск общего текста с помощью DiffUtils

DiffUtils — это статический вспомогательный класс, используемый движком диффа для поиска общего префикса и суффикса, общих двум строкам, до того как различающаяся средняя часть будет сравниваться. FindCommonStartParts находит общий префикс, а FindCommonEndParts — общий суффикс; перегрузка FindCommonEndParts принимает startIndex, чтобы поиск суффикса мог быть ограничен текстом, следующем за уже найденным префиксом.

string original = "The quick brown fox";
string revised = "The quick red fox jumps";

var commonStart = DiffUtils.FindCommonStartParts(original, revised);
var commonEnd = DiffUtils.FindCommonEndParts(original, revised);

Воссоздание текста из диффа

Как только diff выражен как последовательность значений DiffOperation, DiffUtils может восстановить любую из сторон сравнения: AssemblySourceText восстанавливает оригинальный текст из Equal и Delete запусков, а AssemblyDestinationText восстанавливает исправленный текст из Equal и Insert запусков.

using System.Collections.Generic;

var diffs = new List<DiffOperation>
{
    new DiffOperation(Operation.Equal, "The quick "),
    new DiffOperation(Operation.Delete, "brown"),
    new DiffOperation(Operation.Insert, "red"),
    new DiffOperation(Operation.Equal, " fox")
};

string sourceText = DiffUtils.AssemblySourceText(diffs);
string destinationText = DiffUtils.AssemblyDestinationText(diffs);

Console.WriteLine(sourceText);      // "The quick brown fox"
Console.WriteLine(destinationText); // "The quick red fox"

Сравнение и отчет об изменениях

DiffOperation переопределяет Equals, GetHashCode и ToString, поэтому изменения можно сравнивать на равенство или записывать в журналы и вывод тестов без дополнительного кода преобразования.

var a = new DiffOperation(Operation.Equal, "PDF");
var b = new DiffOperation(Operation.Equal, "PDF");

bool same = a.Equals(b); // true - same Operation and Text
Console.WriteLine(a.ToString());

Советы и лучшие практики

  • DiffOperation неизменяемый и реализует IEquatable<DiffOperation> — используйте Equals для сравнения двух правок вместо сравнения ссылок.
  • Сначала найдите общий префикс с помощью FindCommonStartParts, затем передайте его длину в перегрузку startIndex функции FindCommonEndParts, чтобы избежать двойного учёта короткого общего префикса в качестве части суффикса.
  • Используйте AssemblySourceText и AssemblyDestinationText для проверки того, что последовательность значений DiffOperation корректно возвращается к точному оригинальному и исправленному тексту, прежде чем полагаться на неё в другом месте.
  • Считайте запуски Operation.Equal пустыми операциями при построении визуального diff и подсвечивайте только запуски Delete и Insert.
  • Этот движок делает diff текста, а не документов напрямую— извлеките текст, который хотите сравнить (например, со страницы или из документа), прежде чем создавать diff.

Распространённые проблемы

ПроблемаПричинаИсправление
AssemblySourceText / AssemblyDestinationText вывод не совпадает с оригиналамиСписок diffs неполный или его DiffOperation записи находятся в неправильном порядкеВключите каждое изменение в последовательность в оригинальном порядке, в котором они произошли
FindCommonEndParts возвращает неожиданный результат на коротких, похожих строкахПоиск общего суффикса перекрывает текст, уже сопоставленный FindCommonStartPartsПередайте длину, возвращаемую FindCommonStartParts, в качестве аргумента startIndex
Equals возвращает false для правок, которые выглядят одинаковоЗначения Text различаются пробелами или регистромНормализуйте текст (обрезка / приведение к одному регистру) перед построением значений DiffOperation, которые вы собираетесь сравнивать
Вывод diff выглядит шумным или излишне фрагментированнымНеобработанные последовательности DiffOperation ещё не канонизированыПропустите последовательность через этап оптимизации, описанный в Оптимизация diff

FAQ

Что сравнивает движок Diff?

Он сравнивает последовательные блоки текста и генерирует последовательность значений DiffOperation, описывающих правки— неизменённый, удалённый или вставленный текст— необходимые для преобразования одной строки в другую.

Какие типы правок поддерживает Operation?

Три: Equal для неизменённого текста, Delete для текста, удалённого из источника, и Insert для текста, добавленного в целевой документ.

Как проверить, одинаковы ли две правки?

Вызовите Equals у экземпляра DiffOperation, или сравните его свойства Operation и Text напрямую.

Можно ли получить исходный и изменённый текст из diff?

Да — передайте список значений DiffOperation в DiffUtils.AssemblySourceText для исходного текста и в DiffUtils.AssemblyDestinationText для изменённого текста.

Эта страница охватывает слияние или очистку diff?

Нет — канонизация необработанного diff (объединение соседних участков, скольжение правок через равенства) рассматривается отдельно в Оптимизация diff.


API Reference Сводка

Класс / МетодОписание:
OperationПеречисление, классифицирующее правку как Equal, Delete или Insert
DiffOperationОдна правка: Operation, связанный с Text, к которому она применяется
DiffOperation.OperationЗначение Operation для этой правки
DiffOperation.TextПоследовательность текста, к которой применяется это изменение
DiffOperation.EqualsСравнивает два изменения на равенство по Operation и Text
DiffOperation.ToStringПреобразует изменение в строку для журналирования или отображения
DiffUtilsСтатический вспомогательный класс с утилитами для диффа текста
DiffUtils.FindCommonStartPartsНаходит общий префикс, общий для двух строк
DiffUtils.FindCommonEndPartsНаходит общий суффикс, общий для двух строк, опционально начиная с индекса
DiffUtils.AssemblySourceTextВоссоздаёт оригинальный текст из списка значений DiffOperation
DiffUtils.AssemblyDestinationTextВоссоздаёт исправленный текст из списка значений DiffOperation

См. также:

 Русский