牛津高阶双解第四版光盘数据简单分析和提取

看到论坛上还有许多人对牛津高阶双解第四版很感兴趣,也有人为了完善此词典而不断修正。然而此词典的数据在不断地转制过程中,失真较多,纵有多个版本相互参照,也不一定能校正过来。昨天有个朋友提起,我又找来原光盘的数据看了看,发现里面的数据基本上是明文存储的,研究了一番,最终基本成功提取。

光盘的数据文件在DATA目录中,比较大的文件有三个:JRDCONV.DAT、JRDOVFL.DAT、JRDINDX.DAT。第三个名字一看就知道应该是词条的索引文件。第一个文件最大,词条内容应该就在这里。用Emeditor默认编码打开,里面的英文一览无遗,而且没有加密,中文是乱码,由于原光盘是繁体版,便试着把文本切换到BIG5码看看,果然中文都是正常了!再观察英文,有许多口口不能显示,而且这些口口似乎都是成对出现的,口P口p、口B口i、口I口i、口W口w,对html熟悉的人来说,瞬间就明白这些应该就是html标签。


如果在以前,我可能就直接用emeditor正则批量处理了,可是这些词条之间并没有什么特别独特的标记,导致不好分隔。这时我切换到16进制视图想看看到底有什么规律。然后发现每个词条在大段00后都以非00字符起始,后面再连续几个00字符,这些非0字符接数字顺序排列,最后一个词条是5716,换成10进制就是22294,这就是主词头数目了。

试着用C#写了脚本,以二进制方式读取,判断词头位置,划分词条,替换标签,转为UTF8保存。

//注册big5编码
Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);

//读取JRDCONV.DAT
var jrdconvn = @"D:\WinXpVirt\数据文件\JRDCONV.DAT";
var covnBuffer = File.ReadAllBytes(jrdconvn);

//获取JRDOVFL词条位置
int startPoint = 842; //从此处开始读取
var conlist = new List<int>();
for (var i = 1; i <= 22294; i++)
{
	var serialHex = i.ToString("X4");
	while (startPoint < covnBuffer.Length)
	{
		if (covnBuffer[startPoint -1] == 0x00 && covnBuffer[startPoint -2] == 0x00 && covnBuffer[startPoint].ToString("X2") + covnBuffer[startPoint + 1].ToString("X2") == serialHex && 
			covnBuffer[startPoint + 2] == 0x00 && covnBuffer[startPoint + 3] == 0x00)
		{
			conlist.Add(startPoint);
			break;
		}

		startPoint += 1;
	}
}
conlist.Add(covnBuffer.Length);

//根据词条位置分割词条
List<OALDDef> convDefList = new();

var total = conlist.Count();

Regex r = new Regex("FF00[0-F]{6}"); //删除FF00后面三个字节
for (var s = 1; s < total; s++)
{	
	var sb = new StringBuilder();
	for (var k = conlist[s - 1]; k < conlist[s]; k++)
	{
		sb.Append(covnBuffer[k].ToString("X2"));
	}
	
	var def = sb.ToString();
	var serialHex = def[..4];
	var	content = def[12..];

	//处理同一词条多个FF00的情况
	var arr = r.Replace(content, "FF00 ").Split(" ");

	if (arr.Length > 2)
	{
		for (var f = 0; f < arr.Length - 1; f++)
		{
			if (f < arr.Length - 1)
			{
				convDefList.Add(
					new OALDDef()
					{
						SerialTag = $"{serialHex}_{f}",
						SerialHex = serialHex,
						Def = arr[f]
					});
			}
			else
			{
				convDefList.Add(
					new OALDDef()
					{
						SerialTag = $"{serialHex}_{f}",
						SerialHex = serialHex,
						Def = arr[f] + arr[f + 1]
					});
			}

		}

	}
	else
	{
		convDefList.Add(
			new OALDDef()
			{
				SerialTag = serialHex,
				SerialHex = serialHex,
				Def = r.Replace(content, "FF00")
			});
	}

}

初步生成的文本如下,看起来似乎稍加处理就能用了。然后就又发现了个问题,好多词条都不完整,只有一半,另一半数据呢?答案就是在JRDOVFL.DAT这个文件中。

JRDOVFL.DAT这个文件,每个词条在几个00后都也是以非00字符起始,这些字符也是词条序号,和JRDCONV.DAT文件中词条序号对应。一开始以为只要把这些词条追加到JRDCONV.DAT文件相应词条后面就行了,可生成后发现并不对。这个文件中有好多词条都是出现多次,需要插入到JRDCONV.DAT文件中同一词条的不同部分,这些要插入的位置都是以FF00起始。FF00后面的三个字节没看出来和JRDOVFL.DAT中的词条有什么对应关系。这就给两个文件中的词条合并增加了些困难。好在同一词条不同部分都是以先后出现的顺序插入,于是就用这个办法,以我有限的编程知识,循环套循环的实现。

经过多次调整,最后算是把词典数据基本还原了。不过也不能完全保证数据完全还原,有些词条的末尾处有数据编号,没看出具体作用,可能和图片声音有关吧。代码和提取后的数据我都放出来了,想动手的人可以照此思路和方法自己试着提取。由于光盘版本身有些数据就有问题,所以提取出来的数据也非完美。有人想要完善的可在此基础上继续加工,或可以以此数据和现在数据作校对用。需要注意的是,如果以此制作词典,不要轻易删除数据,不要轻易把繁体转简体,以免再犯前人的问题。

链接: [url]https://pan.baidu.com/s/1HYBprhXAT4aoyDKe7u-Evw?pwd=b2tt[/url] 提取码: b2tt

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇