一直苦于没有好用的词典,心想这东西也无非就是个key-value pair吧,怎么就没人弄个免费好用的呢?

胡正那个Stardict倒是不错,可惜词典有版权问题,结果在sourceforge上关停了,此人也不知所踪了。

于是心想自己搞搞看吧。找了找Stardict的词典格式,没想到设计得还挺合理的。

每本词典主要由三个文件组成:.ifo/.idx/.dict。

.ifo是词典信息,格式类似配置文件,非常短,包括:词典收录词数,单词索引文件大小,单词释义文件格式定义等等。

.idx是单词索引,格式是这样的:每个单词以null-terminated字符串表示,后跟其释义在释义文件中的offset和length(都是4-byte unsigned int,network byte order)。这样从前往后扫这个.idx,就可以知道所有单词的释义都在释义文件的什么地方。

.dict是单词释义。因为.idx已经为每个单词指定了在.dict中的offset和length,那.dict的格式就比较随意了。不过一般都会设置samet ypesequence,这样看上去比较规整。像朗道英汉词典的.dict就是一堆文本。不过也支持其他诸如HTML/MediaWiki,乃至wav等格式的数据。

写了一个可以初步处理朗道英汉词典的程序,得益于良好的格式规范,程序比想象中的简单:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

char ifo[1024];
char idx[1024];
char dict[1024];

int getsize(FILE *fp)
{
    int current = ftell(fp);
    fseek(fp, 0, SEEK_END);
    int size = ftell(fp);
    fseek(fp, current, SEEK_SET);
    return size;
}

int getvalue(FILE *fp, int offset, int length, char *buf)
{
    fseek(fp, offset, SEEK_SET);
    fread(buf, length, 1, fp);
    buf[length] = 0;
}

int main(int argc, char *argv[])
{
    strcpy(ifo, argv[1]);
    strcpy(idx, argv[2]);
    strcpy(dict, argv[3]);

    // open idx file
    FILE *fp_idx = fopen(idx, "rb");
    int size_idx = getsize(fp_idx);
    //printf("%d\n", size_idx);

    // open dict file
    FILE *fp_dict = fopen(dict, "rb");

    // set counter
    int cnt = 5;

    // pull out each word from idx
    char name[512];
    char value[4096];
    uint offset;
    uint length;
    int name_ix = 0;
    char c;
    while (ftell(fp_idx) != size_idx && cnt > 0) {
        fread(&c, 1, 1, fp_idx);
        if (c != 0) {
            name[name_ix++] = c;
        } else {
            // null-end name
            name[name_ix] = 0;

            // get offset and length
            fread(&offset, sizeof(offset), 1, fp_idx);
            fread(&length, sizeof(length), 1, fp_idx);

            // correct byte order
            offset = htonl(offset);
            length = htonl(length);

            // get value
            getvalue(fp_dict, offset, length, value);

            // output result
            printf("%s\n", name);
            printf("%s\n", value);

            // re-initialize
            bzero(name, sizeof(name));
            name_ix = 0;

            cnt--;
        }
    }
    fclose(fp_idx);
    fclose(fp_dict);
    return 0;
}

既然词典格式这里很容易就搞定了,那么真就可以考虑一下弄个Wikipedia那样的人人皆可编辑的词典了。猜想可能有人做过了,不过我还真没见到特别靠谱的开源且无 版权限制的英汉词典。

Links: