Сравнение документов
Сравнение документов
Это руководство показывает, как сравнить два варианта текста и получить последовательность правок между ними, используя движок 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 |