Is it possible to extract plain text wordlists from the system dictionaries in Yosemite?
Best Answer
Indeed it's possible to extract dictionaries:
Someone else already investigated the issue and published the result in his blog.
The quintessence:
Copy the code below and paste it in a *.c document named dedict.c:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include "zlib.h"
#define CHUNK 16384
/*
40 Length of the zlib stream
4c 0020
54 0275 number of blocks
60 808c pointer to the next block
64 8088 length of the first block
68 047a4a length of the unpacked block
6c start of the zlib stream
80fc second block
13cd134
13cd174
*/
int unpack(unsigned char *in, int len)
{
int ret,outed=0;
unsigned have;
z_stream strm;
unsigned char out[CHUNK];
strm.zalloc = Z_NULL;
strm.zfree = Z_NULL;
strm.opaque = Z_NULL;
strm.avail_in = 0;
strm.next_in = Z_NULL;
ret = inflateInit(&strm);
if (ret != Z_OK)
return ret;
strm.avail_in = len;
strm.next_in = in;
do {
strm.avail_out = CHUNK;
strm.next_out = out;
ret = inflate(&strm, Z_NO_FLUSH);
assert(ret != Z_STREAM_ERROR); /* state not clobbered */
switch (ret) {
case Z_NEED_DICT:
ret = Z_DATA_ERROR; /* and fall through */
case Z_DATA_ERROR:
case Z_MEM_ERROR:
(void)inflateEnd(&strm);
return ret;
}
// printf("%lx %x\n",strm.next_in-in,strm.avail_in);
have = CHUNK - strm.avail_out /* - (outed?0:4)*/;
int off = 0;
/*
while (have - off > 3 && out[off] != '<' && out[1+off] != 'd' && out[2+off] != ':') {
++off;
}*/
if (have - off <= 3) {
fprintf(stderr, "could not find entry\n");
}
if (fwrite(out + off/*+(outed?0:4)*/, have - off, 1, stdout) != 1 || ferror(stdout)) {
(void)inflateEnd(&strm);
return Z_ERRNO;
}
//exit(0);
outed+=have;
} while (strm.avail_out == 0);
printf("%06x\n",outed);
(void)inflateEnd(&strm);
return ret == Z_STREAM_END ? Z_OK : Z_DATA_ERROR;
}
char filename[256];
int main(int argc,char **argv) {
FILE *fin; int limit,blen=0,p,l,bcnt=0; unsigned char *buf=NULL;
assert(argc >= 2);
sprintf(filename,"/Library/Dictionaries/%s.dictionary/Contents/Body.data",argv[1]);
if((fin=fopen(filename,"rb"))) {
fseek(fin,0x40,SEEK_SET);
fread(&l,1,4,fin);
limit=0x40+l;
p=0x60;
do {
fseek(fin,p,SEEK_SET);
fread(&l,1,4,fin);
// if(0==l) break;
if(blen<l) {
if(buf!=NULL) free(buf);
blen=l;
buf=(unsigned char *)malloc(blen);
}
fread(buf,1,l,fin);
//fprintf(stderr, "%x@%06x: %x>%06x\n",bcnt,p,l,((int *)buf)[1]);
unpack(buf+8,l-8);
p+=4+l;
++bcnt;
} while(p<limit);
free(buf);
fclose(fin);
}
return 0;
}
and this code and paste it in a *.c document named strip.c:
// This program strips the first 4 characters from each line in the input
#include <stdio.h>
int main() {
while(!ferror(stdin) && !feof(stdin)) {
size_t len = 0;
char *line = fgetln(stdin, &len);
if (!line) break;
if (len > 4)
fwrite(line + 4, 1, len - 4, stdout);
}
return 0;
}
Then open Terminal and cd to the folder containing the two *.c files and execute (in the example one of the dicts in /Library/Dictionaries/ is used, you may use any other in the same folder and then have to replace the name "Oxford Dictionary of English" in line 3 below):
Many people have tried to find the files for Apple's spell check dictionaries but I don't recall any successes.
As for the Language tab in Language & Text, it really doesn't have anything to do with spelling as such, although the top item on the list can set the default spell check dictionary in some circumstances. The top item on the list also sets the OS and app language (for the 22 that are available), the default collation order, and the preferred language requested by Safari. The order of the list can determine the app language used if a localization for the top item is not available. The order can also determine whether a Japanese or Chinese font is used for text which is ambiguous in that regard. I think adding an item to the list can sometimes provide additional encodings in Mail app.
Best Answer
Indeed it's possible to extract dictionaries:
Someone else already investigated the issue and published the result in his blog.
The quintessence:
Copy the code below and paste it in a *.c document named dedict.c:
and this code and paste it in a *.c document named strip.c:
Then open Terminal and cd to the folder containing the two *.c files and execute (in the example one of the dicts in /Library/Dictionaries/ is used, you may use any other in the same folder and then have to replace the name "Oxford Dictionary of English" in line 3 below):
First four results visible in words (it's getting better later):
This should work at least in OS X 10.7 - 10.10.