不幸的是,我只能提供部分一。在这里,由于这个问题对我来说是不能解决的,需要比我聪明的人:-) 也许你会发现“问题”部分很有用,因为在开始实施解决方案之前,您可能需要对此进行研究。
使用情况
我想知道用例可能是你的问题的背后,以便更好地了解它。我在考虑以下内容: 用户(可能是教授)会将2个Word文档(可能是论文文档)上传到网站,以查明它们是否是彼此的副本。 您希望通过单词列表进行比较,因为文档可能包含相同的内容,但顺序不同(编写论文的学生已对句子进行了重新排序)。 网站用户可能希望对文档内容有不同的看法,但不是Microsoft Word自带的内容,因为a)用户可以直接比较Word中的文档,因此不需要使用网站和b)如果句子已经重新排序,Word中的比较是无用的。
那么,有什么用?正如你已经提到的,我们可以从word文档中提取单词列表。首先,我们要计算这些词,以便我们稍后可以计算百分比的差异。 然后我们比较两个列表并找出差异。我们仍然得到两个列表:1)文件A中的文字,但不是文件B和2中的文字)反之亦然。 仅仅显示这两个列表可能已经很有趣了,但似乎您希望更进一步:将Word文档作为一个整体显示并突出显示差异。
的问题
阅读Word文档。这应该很容易。我建议在这里使用Codeplex DocX,因为我之前使用过它,并且不需要安装Office。但是,它仅适用于Docx文件格式。
提取单词列表。有点棘手,因为我们需要考虑单词分隔符,它可能不仅仅是空格。
缩小列表的差异。这应该很容易。
显示差异。可能是最棘手的部分,如果你想得到它的权利。您已经为比较组件提出了建议。但是,我担心这样的组件使用内置的机制来找出差异 - 这正是我不想要的,就我的用例而言。 但还有一个更糟糕的问题:在正确的地方突出显示不同的单词。我需要一个例子来形容它:
Word文档
这是由学生复制一个句子。然后它包含 这里的其他东西。
的Word文档B
这是由学生复制一个句子。然后它包含一个 第二句话。
文件A中不在文件B中的单词:其他,在这里。
文件B中不在文件A中的单词:a,second,sentence。
让我们现在突出显示差异。在文件A中,这不是一个问题:只要突出显示这些单词,它就会是完美的。 然而,在文件B中,我们如何知道是否要在第一句或第二句中突出显示“a”和“句子”这两个词?
当然,对于人类来说,第一句话是相同的,第二句话中的差异很明显。 这样的事情可能已经(或至少试图被)所有的差异工具已经解决了,我只想提一下,根据使用情况,重要的是不要几乎不打破文字文档到一个简单的单词列表。
我的解决方案
阅读word文档:
using Novacode;
DocX.Load(Path.Combine(mydocumentPath, @"DocumentA.docx"));
提取单词的列表:
private static IList ExtractWords(DocX doc)
{
// Get all the text without the headlines
var text = doc.Text;
// Maybe you want to tweak this and more items or use a different approach,
// e.g. using Regex like proposed by @Omri Aharon
var separators = "\r\n\"”“„?«» .!?,{}[]-".ToCharArray();
var strings = text.Split(separators, StringSplitOptions.RemoveEmptyEntries);
return strings.ToList();
}
缩小清单,以区别:
private static void ReduceToDifferences(IList wordsA, IList wordsB)
{
// Maybe there's some optimization possible,
// e.g. loop over the list with fewest entries or something
for (int i = wordsA.Count - 1; i >= 0; i--)
{
// Find word of list A in list B
var word = wordsA[i];
var index = wordsB.IndexOf(word);
// If found, remove it in both
if (index > -1)
{
wordsB.RemoveAt(index);
wordsA.RemoveAt(i);
}
}
}
显示差异:如上所述,这只是部分答案,对于上述问题,我不提供解决方案。
短,自包含的,正确的示例
为了完整起见,并提供一个SSCCE,这里是我的应用程序的其他部分,使其工作。
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Novacode;
static void Main(string[] args)
{
var wordsA = ExtractWords(DocX.Load(Path.Combine(mydocumentPath, @"DocumentA.docx")));
var wordsB = ExtractWords(DocX.Load(Path.Combine(mydocumentPath, @"DocumentB.docx")));
ReduceToDifferences(wordsA, wordsB);
Console.WriteLine("------ Words only in A:");
PrintList(wordsA);
Console.WriteLine("------ Words only in B:");
PrintList(wordsB);
Console.WriteLine("------ Press any key");
Console.ReadLine();
}
private static void PrintList(IList wordsA)
{
foreach (var word in wordsA)
{
Console.WriteLine(word);
}
}