GCIDE:一个完整的英语词典






4.95/5 (29投票s)
一个带搜索引擎和图形文本显示功能的词典,价格低廉。
词典编纂变得简单
你不需要计算尺来拼写,也不需要知道“词典编纂者”是什么意思,就能欣赏一部好的词典。假设你正在用网页浏览器阅读一篇重要的文档,或者正在看CodeProject文章中某个代码狂热者的胡言乱语,你需要查一下“lexicography”(词典编纂)这个词,因为你想知道Lex Luther(莱克斯·卢瑟)是否与它有关,因此你是否应该担心。你可以伸手去拿你书架上那盒过期了的披萨后面放着的袖珍词典,它从来没有你高中时遇到的那些莎士比亚古英语的词汇,或者,如果你已经运行了这个程序,你可以用鼠标选中这个词,右键单击,然后“复制”。你刚下载的GCIDE词典会检测到Microsoft剪贴板上的这个词,并将其视为一个命令,搜索英语查找表并告诉你,lexicography是
:制作词汇表或词典的艺术、过程或职业;制作词典所应用的原则。
你会感到内心暖暖的。
GCIDE:GNU协作英语国际词典
GCIDE 的作者如此描述他们的项目:
这个电子词典是一个正在进行的项目的起点,旨在通过所有愿意帮助建立一个大型且免费的知识库的个人的努力,开发一个现代化的在线综合百科全书式词典。我们请求任何愿意协助创建免费在线访问的综合、有组织的知识库的个人提供数据、时间和精力。
本质上,它是一个免费的在线词典,包含超过 123,000 个词条,可以作为 26 个 XML 文档(每个字母一个)的集合下载,或者下载一个 64MB 的 XML 文档(太大,无法放入内存!)。上面列出的网站有一个“词头”搜索功能,你可以用它来查找词典中的词,但我有更好的方法。当然,这个项目如果没有创建原始 XML 文件并免费在网站上提供的人们的努力,是不可能存在的。所以,我欠他们一份感谢。
下载 XML 文档
如上所述,你可以免费下载所有内容。但由于原始 XML 文档有 64MB,此应用程序要求你不仅要下载此文件,然后将其中包含的词条分成 123742 个单独的 XML 文件,然后使用这些文件构建查找表,以便最终产品可以完成所有工作。本文附带的源代码包含三个单独的程序:
- 创建 XML 文件
- 构建查找表
- 词典
因此,当你下载源代码后,你还需要下载这个文件,解压它,然后将文件 'gcide-entries.xml'(64MB)保存到子目录:\GCide\GCide_Create_XML_Files\GCide_Create_XML_Files\gcide-entries.xml,并运行“创建 XML 文件”程序。
你大概会猜到,生成 123000 个文件需要很长时间,如果你猜对了,那么你是正确的。但是,你不需要一次性完成所有工作,你可以关闭进度反馈窗口(那个显示剩余文件数量的窗口),然后会弹出一个消息框,询问你是否要退出。下次你想重新启动时,它会问你是否要“继续上次未完成的重建?”,你点击“是”,它就会从你上次停止的地方继续。在我的笔记本上,大约需要 15 个小时!这看起来很痛苦,但如果你在晚上运行它,就没那么糟糕了。而且,它不会阻止你做其他大多数事情,所以你可以让它在后台运行,而你做其他事情,但请注意,它会显著降低你的处理器速度。
原始文档包含(有)一些不可打印的“打印控制”字符,它们在内存中占用的字节数不总是相同的(一位作者告诉我,这些字符很快就会被修正),尽管在 `string.Length` 方法中它们只算作一个字符。这就是为什么我花了一个星期才让查找表工作起来的原因。这是一个棘手的问题,我花了很长时间才弄清楚,但最终意识到,成千上万的文件中只有三四个(甚至一个!)打印控制字符导致了我所有的麻烦。由于查找表存储在文件流中,因此文件流由位于精确位置的均匀间隔的记录组成,它们可以以随机访问的方式轻松存储和检索;然而,当一个字符占用一个额外的字节时,该记录就变得不可读,整个系统就会崩溃。
为了识别这些有问题的文件并进行更正,我添加了一个触发警报的 `validWord` 函数。当这个警报响起时,重建查找表的进程会暂停,并弹出一个消息框,询问你是否要重试,这可能是你已经在测试函数中添加了另一个可接受的字符到 `valid-characters` 字符串,或者在有问题的 XML 文档中进行了更正。
在发现这些有问题词条(有十五个词条有错误)后,我在我的电脑上更正了 XML 文档,然后将它们包含在 `Create_XML_Files()` 程序中,以便该程序能够将这些更正后的文件复制到你电脑上生成的有错误的文件上。这样,你就无需处理任何问题。只需坐享其成。当它生成完所有 123000 个文件后,它将覆盖创建 `Rebuild Look-Up Table` 程序问题的 15 个文件,然后你就可以将其连接到可搜索的查找表中了。
查找表
在之前一篇名为“拼写正确,语法看你自己”的 CodeProject 文章中,我解释了查找表的工作原理,但没有提供源代码,因为其中提到的早期项目涉及的数据太大,无法发布在 CodeProject 网站上(>1GB!)。但是,使用这个 GCIDE 词典,你可以在这里下载源代码,并亲眼看看它是如何工作的,当你使用前面提到的 GCIDE 网站上提供的 XML 文件运行时。你可能还是想阅读那篇文章,但即使不读,你也能从本文接下来的内容中获得大致的了解。
你下载的代码会处理 GCIDE 词典中的每个词条,生成所有其变体拼写,同时保留生成各种拼写的方式,然后将它们输入到查找表中,以便稍后检索和显示给用户。这个查找表(LUT)由一个二叉树组成。树中的每个叶子都有一个右、左和下一个指针,以及词语信息和文件 ID,指示在哪里可以找到定义。
存储此数据的方式是文件流。树的每个叶子称为一个记录。并且,树中的每个记录(所有记录都存储在同一个文件流中)大小完全相同。这使得程序可以索引每个记录,并使用诸如
classLUT_Bin_Rec loadbinRec(long index)
{
classLUT_Bin_Rec binRecRetVal = new classLUT_Bin_Rec();
fsBin.Position = getBinRecPosition(index);
binRecRetVal.Word = (string)formatter.Deserialize(fsBin);
binRecRetVal.typeWord =
(enuTypeWord)((int)formatter.Deserialize(fsBin));
binRecRetVal.FileID = (string)formatter.Deserialize(fsBin);
binRecRetVal.left = (long)formatter.Deserialize(fsBin);
binRecRetVal.right = (long)formatter.Deserialize(fsBin);
binRecRetVal.next = (long)formatter.Deserialize(fsBin);
return binRecRetVal;
}
和
void saveBinRec(long index, classLUT_Bin_Rec binRec)
{
fsBin.Position = getBinRecPosition(index);
formatter.Serialize(fsBin, binRec.Word);
formatter.Serialize(fsBin, (int)binRec.typeWord);
formatter.Serialize(fsBin, binRec.FileID);
formatter.Serialize(fsBin, binRec.left);
formatter.Serialize(fsBin, binRec.right);
formatter.Serialize(fsBin, binRec.next);
}
这样的函数,它可以快速轻松地保存或检索所需的任何记录。由于这些记录有指向左子节点、右子节点或下一个同级节点的“指针”,尽管记录是按照它们创建的随机顺序(随机是因为二叉树需要非有序插入才能保持平衡)排列并像一维数组一样索引,但它们被链接成一个二叉树,树的根是文件中的第一个记录。因此,通过从根节点向下遍历树来搜索,当我们要查找的词在字母顺序上早于当前记录中存储的词时,我们就向下走到“左子节点”,或者当你要查找的词在字母顺序上晚于当前记录中存储的词时,搜索算法会向下走到“右子节点”,直到它到达一个空指针(在实现中是 -1,因为它们是我们正在查找的记录的非常长的整数索引),在那里应该找到你正在寻找的词,或者当它找到要找的东西时就停止。
“下一个同级”索引用于具有多个来源的词拼写。例如,单词“runs”在 GCIDE LUT 中出现三次:
- 名词复数
- 动词现在时第三人称单数(跑)
- 动词现在时第三人称单数(使……跑,例如,run a horse)
这三个词的拼写相同,并且来自三个不同的词条,其中一个是名词,另外两个是动词。
从上面的例子中可以看出,单词“fascinate”在其定义中包含了其过去分词“fascinated”和现在分词“fascinating”。(另外,你可能会注意到,词源中的希腊字符在这个屏幕截图被拍摄的计算机上仍然是“不可打印”字符,但由于它们不出现在词形态或变位形式标签之间,所以它们不用于输入 LUT,只是按照它们在 XML 文件中出现的方式保留。)
下面的文件展示了一个由 `BuildLUT` 程序生成的词条示例,它只需在单词“bunt”后面加上“ing”。你可以在 `classEnglish_LUT.cs` 文件中的 `getNounSolution()`、`getVerbSolutions()` 和 `getAdjectiveSolutions()` 函数中找到这些变体拼写的规则以及如何生成它们。
GCIDE 中的词条并不都有其“词形变化”,因此许多词条需要使用简单的语法规则来生成,然后才能插入到查找表中。这有助于搜索单词,因为你不再需要猜测一个词的标题在字典中会如何显示,这比许多其他电子词典有了很大的改进,而许多其他电子词典并不总是理想的。另外,由于应用程序的输入会尝试删除常见的前缀和后缀,并尝试所有组合,直到找到匹配项或耗尽所有可能性后退出,所以你甚至可以找到像“noncredibleness”这样的虚构词。在 GCIDE LUT 中搜索的结果是“non + CREDIBLENESS”,它显示为“credibleness”的定义,以及被移除的前缀“non-”。
运行“build LUT”在普通笔记本电脑上只需要大约四个小时,所以大多数家用电脑可能可以在三个小时内完成。
你自己的词典
`classGCide.cs` 和 `classEnglish_LUT.cs` 文件可以用作其他项目的 DLL,或者你可以编译本文源代码附带的词典应用程序。一旦你下载了原始 XML 文档,创建了 123K 个文件,**并且**构建了你的查找表(LUT),你就可以使用词典应用程序了,它有一些方便的功能。
但首先,让我告诉你关于输出屏幕。你看到的是一个**位图**。所以,如果你喜欢富文本框,当你查看这个输出时,你会有些东西可以玩。富文本框让我很烦恼。所以我创建了一个名为 `classGraphicText` 的类,它在灵活性方面仍然可以有所发展,但在这个项目上只花了几个星期,在图形文本方面可能只用了两天,它已经相当不错了。
图形文本
这个类接收文本字符串并创建一个 `classWordImage` 元素的数组。每个元素包含文本、字体、颜色、一个位图以及相对于数组中前一个元素的 त्याच्या位置。然后,给定所需的图像宽度,该函数
public Bitmap putImageArrayOntoBitmap(int intWidth,
classWordImage[] udrWordArray)
将这些单词图像数组并排(或在需要时换行)组合到单个位图中,并将其返回给调用函数。类中有一个方便的输出窗体,它已准备好使用,并且有自己的垂直滚动条,用于控制位图的位置,当你想要向下滚动文本时。它还会响应任何大小更改,以便重新生成输出位图以适应新大小。
这是一个例子
下面,你将看到当我们把上面的第一个图像的窗体宽度减小时会发生什么。窗体的 `sizechange` 事件处理程序会为新大小调用 `classGraphicText` 的 `putImageArrayOntoBitmap()` 函数,图像(单词)会重新排列,以符合位图,遵循与几乎所有文字处理器或文本编辑器使用的“自动换行”类似的规则
如果你以后需要为屏幕上的其他内容腾出空间。
再看一个二叉树
由于为用户找到的每个结果中的每个单词绘制所有单独的位图有点慢,我创建了一个先前创建的单词条目的二叉树,并在生成任何新位图之前对其进行扫描。当单词(拼写完全相同,包括其后面的标点符号,具有完全相同的字体、大小和颜色)不存在于二叉树中时,那么即将创建的那个单词就会存储在树中并供以后引用。而且,当你要找的图像已经存在时,那么那个单词的 `classWordImage` 元素的位图字段指针就会指向留在 `WordImage` 二叉树中的那个元素中的位图。
二叉树可以在 `classGraphicText` 的
public bool WordSetInBinTree(ref classWordImage wordImage)
函数中找到。
附加功能
再仔细看看上面的漂亮图片。你会注意到词典窗体底部的两个复选框。左边的第一个允许你从任何其他应用程序(无论是你的网页浏览器还是文字处理器)使用词典;只需突出显示你要查找的单词,然后按下 Ctrl-C 或 Ctrl-X 键,当单词出现在 Windows 剪贴板中时,词典会将它视为一个搜索命令,就像你在窗体顶部的文本框中输入该单词并按下 Enter 键一样。
第二个复选框允许你点击位图并定义你点击的任何单词。这是通过 `classGraphicText.Panel_GraphicText` 的
public classWordImage getWordUnderMouse()
函数实现的,并在处理 `mouse_click` 事件时调用。
作为奖励,你可以玩一个游戏。不使用键盘,只用鼠标,尝试从“zebra”点击到“aardvark”。这会花你几个小时!
更新版本
在这个 GCIDE 词典的新更新版本中,现在有第三个复选框,上面写着“Popup Mouse Hover DEfinition”(鼠标悬停弹出定义)。
当勾选此项时,鼠标光标下的任何单词,当你让它悬停时,都会出现其自己的弹出定义。一个列表框会出现在鼠标光标下方,单词的前面,旁边是一个带有该单词定义的弹出窗体。鼠标滚轮允许你在弹出定义上滚动,如果你要查看的单词对于这个拼写有多个来源,你也可以将鼠标向下移动到列表框中列出的任何其他条目。
代码注释
我为代码添加了一些注释,并在我认为需要解释的地方进行了详细说明,但在许多情况下,函数的名称本身就足以说明问题,所以你应该可以轻松地使用这些类。