文档比较

文档比较

本指南展示了如何比较两段文本的运行结果,并使用针对 .NET 的 Aspose.PDF 开源文本差异引擎生成它们之间的编辑序列。此比较模型的入口点是 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 是 diff 引擎使用的静态辅助类,用于在对不同的中间部分进行差异比较之前,查找两个字符串共享的公共前缀和后缀。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 定位公共前缀,然后将其长度传入 FindCommonEndParts 的 startIndex 重载,以避免短的公共前缀被双重计入后缀。
  • 使用 AssemblySourceText 和 AssemblyDestinationText 验证一系列 DiffOperation 值能往返至完全相同的原始和修订文本,然后再在其他地方依赖它。
  • 在渲染可视化 diff 时,将 Operation.Equal 运行视为无操作,仅高亮显示 Delete 和 Insert 运行。
  • 此引擎对文本进行差异比较,而不是直接对文档——在生成差异之前,请先提取您想比较的文本(例如,从页面或文档中提取)。

常见问题

问题原因修复
AssemblySourceText / AssemblyDestinationText 输出与原始不匹配diffs 列表不完整,或其 DiffOperation 条目顺序错误在序列中包含每一次编辑,保持编辑发生的原始顺序
FindCommonEndParts 在短且相似的字符串上返回意外结果公共后缀搜索与 FindCommonStartParts 已匹配的文本重叠将 FindCommonStartParts 返回的长度作为 startIndex 参数传入
Equals 对看起来相同的编辑返回 falseText 值在空白或大小写上不同在构建要比较的 DiffOperation 值之前,先对文本进行规范化(去除空格/统一大小写)
Diff 输出显得嘈杂或不必要地碎片化原始的 DiffOperation 序列尚未规范化将该序列通过本文所述的优化阶段 Diff 优化

FAQ

Diff 引擎比较什么?

它比较文本块并生成一系列 DiffOperation 值,描述将一个字符串转换为另一个字符串所需的编辑——未更改、删除或插入的文本。

Operation 支持哪些编辑类型?

三种:Equal 表示未更改的文本,Delete 表示从源中删除的文本,Insert 表示在目标中添加的文本。

我如何检查两个编辑是否相同?

在 DiffOperation 实例上调用 Equals,或直接比较其 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 值重新组装修订后的文本

另请参阅

 中文