3

我有一个 Web 应用程序,其中客户端编辑器正在编辑服务器端已知的非常大的文本。

客户端可以对此文本进行任何类型的修改。

以服务器理解的方式传输结果差异的最网络效率的方式是什么?此外,由于这将发生在客户端(Javascript),我也希望它“快”(或至少不会明显慢)

一些场景:

  • 用户修改一个字符
  • 用户在随机位置修改多个句子
  • 用户删除所有内容并导致空白文本。

我不能使用类似 diff 的语法,因为它不是网络高效的,它会检查行,示例 1 和 3 会产生可怕的差异(尤其是最后一个,结果将超过旧的本身)。

有人有这方面的经验吗?用户对大量数据进行操作——大约 3-5MB 的文本,上传整个“新”内容是一个很大的禁忌。

需要明确的是,我正在寻找传输的“协议”,字符串比较不是问题。

4

5 回答 5

3

我对这个主题不是很熟悉,但我可以为您指出一个可能非常有用的开源(Apache 许可证 2.0)项目。

它是一个由 Google 工程师以多种语言(包括 JavaScript)编写的 Diff、Match 和 Patch 库,用于多种在线协作编辑服务。

以下是资源列表:

于 2009-10-16T05:59:19.613 回答
1

一个简单的方法,假设您知道服务器上的副本不会更改,只需发送一个编辑列表(删除和添加),删除表示为开始和结束索引,添加表示作为起始索引和要插入的文本。

如果您使用的不仅仅是一个简单的 diff 算法(我不确定“字符串比较不是问题”的确切含义),您还可以检测移动或复制的文本块,并将其作为开始发送和移动或复制文本的结束索引,以及插入它的目标。

请注意,您需要确保跟踪您的索引是指原始文档还是到目前为止已编辑的文档。避免此问题的一种简单方法是始终从文档末尾向开头执行编辑;那么早期的编辑不会影响后面的编辑指定的偏移量。

有关此类方法的示例,请参阅输出的ed格式diff -e。这基本上是可以输入ed面向行的文本编辑器的输入。如果您希望发送绝对最小的差异,您可能希望进行基于字符的索引而不是基于行的索引,但相同的基本方法可以工作。

于 2009-10-16T04:45:35.540 回答
1

用户执行的任何编辑都可以有效地分解为:从 X 中删除长度为 Y;在 X 处插入文本“随便”。X 和 Y 是相对于文本开头的字符偏移量;Y是字符数;“whatever”是任何字符串。你说你不需要帮助计算差异,但这里有一个例子,除了它的输出比你需要的更丰富,但确实识别“删除和插入”,所以,只需更改输出部分。

可以调整您将数据发送到服务器的确切格式,但我认为这样做没有太多意义 - 待测量,我首先将命令发送为 D 用于删除或 I 用于插入,十进制数字,引号形式的插入字符串。一旦您对正在执行的实际传输进行了一些统计,您就可以看到数字(十进制与二进制)和引号中有多少开销,但我怀疑这可能不是那么有意义(如果证明是,那么所有排序您可以尝试的事情,例如从最新的插入或删除点开始偏移,而不是总是从头开始,以使事情更快)。

您可以每隔几秒钟对用户正在做的事情进行采样,然后在最后几秒钟内发送增量更改(如果有的话)——这样,您发送的每个数据包都会很小,如果网络连接或用户的计算机/浏览器崩溃,用户不会丢失太多工作。

于 2009-10-16T05:14:06.303 回答
0

您可以每 500 毫秒发送一次更改,因此,在最后 500 毫秒内所做的任何更改都将被发送,但您仅在发生更改时发送数据。

然后,您可以在此发送已更改单词的位置并仅发送整个单词,但我希望该位置位于文本的前面。

它不会是几句话的价值,但可能会涉及几个单词,但是,如果您按照更改的顺序发送它们,那么结果应该是一致的。

于 2009-10-16T04:58:17.707 回答
0

因为有很多方法可以进行编辑——即使在 500 毫秒这样的短时间内——包括拖放或剪切和粘贴文档内或文档外部的大段文本——我不知道如果有东西可以很好地涵盖所有场景。从表面上看,这肯定不是您问题的答案,但是与更改界面以限制文本大小并将现有文本分解成更小的部分相比,我会仔细考虑开发和维护此类内容的麻烦。

也许这在您的情况下是不可能的,但如果是这样,我想最终以这种方式回避问题并在编辑后发送完整的文档会少很多麻烦。

于 2009-10-20T18:23:22.197 回答