JAVA版StarDict星际译王简单实现


由胡正开发的星际译王是Linux平台上很强大的一个开源的翻译软件(也有Windows版本的)支持多种词库、多种语言版本。尤其词库设计比较合理。之前看到一篇博文《星际译王词库应用-自制英汉词典》中用简短的程序就实现了词典的基本功能,不过那个是Linux 下的C/C++版本的,于是决定参考移植一个JAVA版本。

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.*;

/**
 * {@docRoot}
 * Java版词典测试版,可以在控制台下输入要查询的单词,回车后会给出单词在词典中的释义
 * 词典采用星际译王的词典,本程序主要针对英汉词典
 * 
 * @author menglongbor
 * @updateDate 2012-12-31
 * @version v1.0.0
 * 
 * 相关参考链接:
 * http://blog.chinaunix.net/uid-20454005-id-1675913.html
 * http://hi.baidu.com/sean_zhu_xiang/item/1581342f88be430e73863eee
 * http://blog.csdn.net/ranxiedao/article/details/7787342
 * http://www.stardict.cn/
 * http://www.huzheng.org/
 * http://code.google.com/p/stardict-3/downloads/list
 * 
 */
public class testdict
{
final static intMAX_WORD= 256;// 最长输入单词字符数
final static intMAX_KEYS= 27;// 26个字母+"-"开头的后缀
final static intSIZEINT= 4;
final static StringKEY[]= {// 26个字母索引+"-"开头的后缀,不区分大小写
"A", "b", "c", "d", "e", "f",
"g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s",
"t", "u", "v", "w", "x", "y", "z", "-" };
public static InputStreamisidx= null;// 读取idx文件时所要的流
public static InputStreamisdict= null;// 读取dict文件时所要的流
public static longSTREAM_LOCAL= 0;// 记录单词索引在文件流中的位置
public static StringidxfileString= "oxford-gb.idx";// idx文件路径
public static StringdictfileString= "oxford-gb.dict";// dict文件路径

/**
* 从idx文件中获取当前目标单词
* @param word_buf 保存的是c/c++字符串数组转换为JAVA字符串
* @param data_poffset 用来保存单词的data偏移位置信息
* @param data_plength 用来保存单词的data长度信息
* @param len
* @return
*/
public static boolean get_word(String[] word_buf, int[] data_poffset,
int[] data_plength, int[] len)
{
// int len = 0;
boolean flag = true;
len[0] = 0;
int index = -1;
byte wd[] = new byte[MAX_WORD];
int value = 0;
try
{
// 读取单词,对每个字母开头的单词都进行搜索,最多考虑256个字符的单词,
// 读到单词结束符\0时赋值表达式的值就不满足while条件而退出
while (true)
{
index = isidx.read();
STREAM_LOCAL++;// 每读取一次,位置标识加一以记录下单词在文件流中的起始位置
if (index == -1)
{
// isidx.reset();
flag = false;
break;
}
if ((index != 0) && (len[0] < MAX_WORD))
{
wd[len[0]] = (byte) index;// 将int转换为byte
len[0]++;
} else
{
break;
}
}
// 转换为JAVA字符串
// 此处不用再需要像c/c++那样去掉了最后那个结束符了
byte wd2[] = new byte[len[0]];
for (int i = 0; i < len[0]; i++)
{
wd2[i] = wd[i];
}
word_buf[0] = new String(wd2);
// System.out.println("get_word:"+word_buf[0]+" len:"+len[0]);
// wd = null;// 释放内存
// wd2 = null;
// 读取偏移量值
for (int i = 0; i < SIZEINT; i++)
{
// 将4个byte转换为int
int shift = (4 - 1 - i) * 8;
index = isidx.read();
STREAM_LOCAL++;// 每读取一次,位置标识加一以记录下单词在文件流中的起始位置
if (index == -1)
{
// isidx.reset();
flag = false;
return flag;
}
value += (index & 0x00FF) << shift;
}
data_poffset[0] = value;
// 读取区块大小值
value = 0;
for (int i = 0; i < SIZEINT; i++)
{
// 将4个byte转换为int
int shift = (4 - 1 - i) * 8;
index = isidx.read();
STREAM_LOCAL++;// 每读取一次,位置标识加一以记录下单词在文件流中的起始位置
if (index == -1)
{
// isidx.reset();
flag = false;
return flag;
}
value += (index & 0x00FF) << shift;
}
data_plength[0] = value;
}
catch (Exception e)
{
System.out.println("idx file read error!");
}
// System.out.println("Now local is:"+STREAM_LOCAL);
// 得到单词字符长度
return flag;

}

/**
* 通过偏移位置offset和长度length 来从dict文件中获取data内容UTF-8编码的字符
* @param offset 要读取的内容的起始偏移,为字节数
* @param length 要读取的内容的数据块大小,为字节数
* @return 字节数组的data int
*/
public static byte[] get_data(int[] offset, int[] length)
{
long oft = offset[0];
long len = length[0];
long skip;
byte data_buf[] = new byte[length[0]];
System.out.println("This word's" + "offset:" + offset[0] + "len:"
+ length[0]);

try
{
isdict.reset();
long valuedata = isdict.available();
if (valuedata < oft + len)
{
System.out.println("No so much value data! " + valuedata);
}
// skip=isdict.skip(oft);
skip = skipBytesFromStream(isdict, oft);
if (skip != oft)
{
System.out.println("Skip" + skip + " dict file error!");
}
if (isdict.read(data_buf) == -1)
{
System.out.println("Arrive at the end of file!");
}

// // Unicode
// StringBuffer sb = new StringBuffer();
//
// int size =isdict.read(data_buf);
//
// for (int j = 0; j < size;)
// {
//
// int l = data_buf[j++];
//
// int h = data_buf[j++];
//
// char c = (char) ((l & 0xff) | ((h << 8) & 0xff00));
//
// sb.append(c);
//
// }
//
// // return sb.toString();

}
catch (Exception e)
{
data_buf = null;
System.out.println("dict file read error!");
e.printStackTrace();
}
if (data_buf == null)
{
return null;
}

return data_buf;
}

/**
* utf8解码 参考自http://hi.baidu.com/leo10086/item/d6853813373b19001994ec24 用法:
* 假如 newContent 为UTF8编码的字符串 byte[] b = newContent.getBytes(); newContent =
* URLEncoder.UTF8Decode( b, 0, b.length );
* @param in 要进行解码的UTF8编码的字节数组
* @param offset
* @param length
* @return
*/
public static String UTF8Decode(byte in[], int offset, int length)
{
StringBuffer buff = new StringBuffer();
int max = offset + length;
for (int i = offset; i < max; i++)
{
char c = 0;
if ((in[i] & 0x80) == 0)
{
c = (char) in[i];
} else if ((in[i] & 0xe0) == 0xc0) // 11100000
{
c |= ((in[i] & 0x1f) << 6); // 00011111
i++;
c |= ((in[i] & 0x3f) << 0); // 00111111
} else if ((in[i] & 0xf0) == 0xe0) // 11110000
{
c |= ((in[i] & 0x0f) << 12); // 00001111
i++;
c |= ((in[i] & 0x3f) << 6); // 00111111
i++;
c |= ((in[i] & 0x3f) << 0); // 00111111
} else if ((in[i] & 0xf8) == 0xf0) // 11111000
{
c |= ((in[i] & 0x07) << 18); // 00000111 (move 18, not 16?)
i++;
c |= ((in[i] & 0x3f) << 12); // 00111111
i++;
c |= ((in[i] & 0x3f) << 6); // 00111111
i++;
c |= ((in[i] & 0x3f) << 0); // 00111111
} else
{
c = ' ';
}
buff.append(c);
}
return buff.toString();
}


public static byte[] UTF8Encode(String str)
{
ByteArrayOutputStream bos = new ByteArrayOutputStream();
try
{
int strlen = str.length();
for (int i = 0; i < strlen; i++)
{
char t = str.charAt(i);
int c = 0;
c |= (t & 0xffff);
if (c >= 0 && c < 0x80)
{
bos.write((byte) (c & 0xff));
} else if (c > 0x7f && c < 0x800)
{
bos.write((byte) (((c >>> 6) & 0x1f) | 0xc0));
bos.write((byte) (((c >>> 0) & 0x3f) | 0x80));
} else if (c > 0x7ff && c < 0x10000)
{
bos.write((byte) (((c >>> 12) & 0x0f) | 0xe0)); // <--
// correction
// (mb)
bos.write((byte) (((c >>> 6) & 0x3f) | 0x80));
bos.write((byte) (((c >>> 0) & 0x3f) | 0x80));
} else if (c > 0x00ffff && c < 0xfffff)
{
bos.write((byte) (((c >>> 18) & 0x07) | 0xf0));
bos.write((byte) (((c >>> 12) & 0x3f) | 0x80));
bos.write((byte) (((c >>> 6) & 0x3f) | 0x80));
bos.write((byte) (((c >>> 0) & 0x3f) | 0x80));
}
}
bos.flush();
}
catch (Exception e)
{
}
return bos.toByteArray();
}


/**
* 将UTF-8字节数据转化为Unicode字符串

* @param utf_data
*            byte[] - UTF-8编码字节数组
* @param len
*            int - 字节数组长度
* @return String - 变换后的Unicode编码字符串
*/
public static String UTF2Uni(byte[] utf_data, int len)
{
StringBuffer unis = new StringBuffer();
char unic = 0;
int ptr = 0;
int cntBits = 0;
for (; ptr < len;)
{
cntBits = getCntBits(utf_data[ptr]);
if (cntBits == -1)
{
++ptr;
continue;
} else if (cntBits == 0)
{
unic = UTFC2UniC(utf_data, ptr, cntBits);
++ptr;
} else
{
unic = UTFC2UniC(utf_data, ptr, cntBits);
ptr += cntBits;
}
unis.append(unic);
}
return unis.toString();
}


/**
* 将指定的UTF-8字节组合成一个Unicode编码字符
* @param utf byte[] - UTF-8字节数组
* @param sptr int - 编码字节起始位置
* @param cntBits int - 编码字节数
* @return char - 变换后的Unicode字符
*/
public static char UTFC2UniC(byte[] utf, int sptr, int cntBits)
{
/*
* Unicode <-> UTF-8 U-00000000 - U-0000007F: 0xxxxxxx U-00000080 -
* U-000007FF: 110xxxxx 10xxxxxx U-00000800 - U-0000FFFF: 1110xxxx
* 10xxxxxx 10xxxxxx U-00010000 - U-001FFFFF: 11110xxx 10xxxxxx 10xxxxxx
* 10xxxxxx U-00200000 - U-03FFFFFF: 111110xx 10xxxxxx 10xxxxxx 10xxxxxx
* 10xxxxxx U-04000000 - U-7FFFFFFF: 1111110x 10xxxxxx 10xxxxxx 10xxxxxx
* 10xxxxxx 10xxxxxx
*/
int uniC = 0; // represent the unicode char
byte firstByte = utf[sptr];
int ptr = 0; // pointer 0 ~ 15
// resolve single byte UTF-8 encoding char
if (cntBits == 0)
return (char) firstByte;
// resolve the first byte
firstByte &= (1 << (7 - cntBits)) - 1;
// resolve multiple bytes UTF-8 encoding char(except the first byte)
for (int i = sptr + cntBits - 1; i > sptr; --i)
{
byte utfb = utf[i];
uniC |= (utfb & 0x3f) << ptr;
ptr += 6;
}
uniC |= firstByte << ptr;
return (char) uniC;
}


/**
* 根据给定字节计算UTF-8编码的一个字符所占字节数,UTF-8规则定义,字节标记只能为0或2~6
* @param b
* @return
*/
private static int getCntBits(byte b)
{
int cnt = 0;
if (b == 0)
return -1;
for (int i = 7; i >= 0; --i)
{
if (((b >> i) & 0x1) == 1)
++cnt;
else
break;
}
return (cnt > 6 || cnt == 1) ? -1 : cnt;
}


/**
 * 显示data内容
 * @param data_buf UTF-8的单词释义数组
 * @param data_length UTF-8的单词释义数组长度
 */
public static void display_data(byte[] data_buf, int data_length[])
{
// 将UTF-8byte字节数组转为当前环境字符并显示
// String tempString = UTF8Decode(data_buf, 0, data_length[0]);
String tempString = UTF2Uni(data_buf, data_length[0]);
// String tempString = new String(data_buf);
data_buf = null;
System.out.println(tempString);


}


/**
* 从idx文件中搜索由word指定的单词,并保存相应的偏移和长度信息
* @param word
* @param data_poffset
* @param data_plength
* @return 是否搜索成功
*/
public static boolean search_word(String word, int[] data_poffset,
int[] data_plength)
{
String wd[] = new String[1];
boolean temp = false;
int len[] = new int[1];
// 从idx文件中获取当前目标单词
// for (get_word(wd, data_poffset, data_plength); end; get_word(wd,
// data_poffset, data_plength))
// {
while (get_word(wd, data_poffset, data_plength, len))
{


// System.out.println("compared_word:"+wd[0]);
// if (wd[0].compareToIgnoreCase(word) == 0) //
// 比较字符串s1和s2,但不区分字母的大小写
if (strsEqualsIgnoreCase(wd[0], word) == 0)
{
System.out.println("compared_word:" + word + " " + wd[0]);
temp = true;
break;
}
}


return temp;
}


/**
 * 从标准输入获取待查询的单词,控制台下为GBK字符,字典索引中的英文单词字母也是如此
 * @param max_len
 * @param count
 * @return
 */
public static String get_input(int max_len, int[] count)
{
byte input_buf[] = new byte[max_len];
count[0] = 0;
String tempString[] = new String[1];
try
{
count[0] = System.in.read(input_buf) - 2;// 返回实际读取到的字符数,减去2个控制字符
byte temp_buf[] = new byte[count[0]];
for (int i = 0; i < count[0]; i++)
{
temp_buf[i] = input_buf[i];
}
tempString[0] = new String(temp_buf);
}
catch (Exception e)
{
System.out.println("Input error!");
}
System.out.println("Your input is:" + tempString[0]);
return tempString[0];
}


/**
 * 从标准输入获取待查询的单词,控制台下为GBK字符,字典索引中的英文单词字母也是如此
 * @param input_buf
 * @param count
 * @return
 */
public static byte[] get_input(byte[] input_buf, int[] count)
{
try
{
count[0] = System.in.read(input_buf) - 2;// 返回实际读取到的字符数,减去2个控制字符
}
catch (Exception e)
{
input_buf = null;
System.out.println("Input error!");
}
return input_buf;
}


/**
* 缓存KEYS在idx中的偏移信息,以便加快search_word的搜索速度
* @param idx_cache 保存每个单字母单词对应的起始位置
* @return
*/
public static void cache_idx(long[] idx_cache)
{
int i;
long[] p = idx_cache;
int unused1[] = new int[1];
int unused2[] = new int[1];
try
{
// 将文件内部的位置指针重新指向一个流(数据流/文件)的开头返回FILE指针当前位置,
// 然后重新遍历整个文件搜寻下一个字母开头的单词
isidx.reset();
STREAM_LOCAL = 0;
for (i = 0; i < MAX_KEYS; i++)
{


// System.out.println("Start search_word:" + KEY[i]);
if (search_word(KEY[i], unused1, unused2))// 从idx文件中搜索由word指定的单词,并保存相应的偏移和长度信息
{
p[i] = STREAM_LOCAL; // 返回当前文件位置
// String tempString = Long.toString(STREAM_LOCAL);
// System.out.println(KEY[i] + "'s local is:" + tempString);
System.out.println(KEY[i] + "'s local is:" + STREAM_LOCAL
+ " offset:" + unused1[0] + "length:" + unused2[0]);
} else
p[i] = 0;


}
// isidx.reset();
}
catch (Exception e)
{
// TODO: handle exception
}


}


/**
* 定位由word指定的单词在idx文件中的大概偏移位置
* @param word
* @param idx_cache
* @return
*/
public static long locate_idx(String word, long[] idx_cache)
{
int i = 0;
int pre = 0;
String tempString = word.toLowerCase();
while (i < MAX_KEYS && KEY[i].charAt(0) < tempString.charAt(0))
{
pre = i;
++i;
}
if (tempString.charAt(0) == '-')
{
pre = 0;
}
System.out.println("Now word's locate is:" + idx_cache[pre]);
return idx_cache[pre];
}


/**
 * 主要查询函数
 */
public static void consult()
{
byte data[] = null;// 释义数据,UTF-8数据
long idx[] = new long[MAX_KEYS];// 26个字母孤立单词+"-"开头的后缀对应的索引缓冲
int offset[] = new int[1];
int length[] = new int[1];
System.out.println("Start cache_idx....!");
try
{
System.out.println("Open files....!");
// 读取字典索引文件
isidx = new BufferedInputStream(new FileInputStream(
idxfileString));
isidx.mark(isidx.available() + 1);
if (!isidx.markSupported())
{
System.out.println("This stream do not support mark....!");
}
}
catch (Exception e)
{
System.out.println("Open files error!");
e.printStackTrace();
}


cache_idx(idx);// 缓存KEYS在idx中的偏移信息,以便加快search_word的搜索速度


try
{
isdict = new BufferedInputStream(new FileInputStream(
dictfileString));
isdict.mark(isdict.available() + 1);
if (!isdict.markSupported())
{
System.out.println("This stream do not support mark....!");
}
}
catch (Exception e)
{
System.out.println("Open files error!");
e.printStackTrace();
}


while (true)
{
System.out.println("INPUT A WORD OR PHRASE: ");
int count[] = new int[1];
String word = get_input(MAX_WORD, count);
long skips1, skips2;
if (count[0] > 0)// 从控制台得到输入单词字符
{
try
{
// 从文件开头跳到单词大致索引所在位置
// isidx.mark(0);
isidx.reset();
skips1 = locate_idx(word, idx);
// skips2 = isidx.skip(skips1);
skips2 = skipBytesFromStream(isidx, skips1);
System.out
.println("skips1:" + skips1 + " skips2:" + skips2);
}
catch (Exception e)
{
System.out.println("locate_idx run error");
e.printStackTrace();
}
if (search_word(word, offset, length))
{
data = get_data(offset, length);
display_data(data, length);
data = null;
} else
System.out.println("SORRY " + word + " CANNOT BE FOUND!\n");
System.out
.println("\n----------------------------------------\n\n");
} else
break;
}
}


/**
* 不区分大小写比较两个字符串

* @param s1
* @param s2
* @return
*/
public static int strsEqualsIgnoreCase(String s1, String s2)
{
int n1 = s1.length(), n2 = s2.length();
for (int i1 = 0, i2 = 0; i1 < n1 && i2 < n2; i1++, i2++)
{
char c1 = s1.charAt(i1);
char c2 = s2.charAt(i2);
if (c1 != c2)
{
// 源字符串全部都转为大写字符串
c1 = Character.toUpperCase(c1);
c2 = Character.toUpperCase(c2);
if (c1 != c2)
{
// 源字符串全部都转为小写字符串
c1 = Character.toLowerCase(c1);
c2 = Character.toLowerCase(c2);
if (c1 != c2)
{
return c1 - c2;
}
}
}
}
return n1 - n2;// 如果其中一个或者两个String都比较完了还没有同样的char的话,那就return两个String的长度差距
}


/**
* 重写了Inpustream 中的skip(long n) 方法,将数据流中起始的n 个字节跳过
* 参考:http://blog.csdn.net/ranxiedao/article/details/7787342
* @param inputStream
* @param n
* @return
*/
private static long skipBytesFromStream(InputStream inputStream, long n)
{
long remaining = n; // SKIP_BUFFER_SIZE is used to determine the size of
// skipBuffer
int SKIP_BUFFER_SIZE = 2048; // skipBuffer is initialized in
// skip(long), if needed.
byte[] skipBuffer = null;
int nr = 0;
if (skipBuffer == null)
{
skipBuffer = new byte[SKIP_BUFFER_SIZE];
}
byte[] localSkipBuffer = skipBuffer;
if (n <= 0)
{
return 0;
}
while (remaining > 0)
{
try
{
nr = inputStream.read(localSkipBuffer, 0, (int) Math.min(
SKIP_BUFFER_SIZE, remaining));
}
catch (IOException e)
{
e.printStackTrace();
}
if (nr < 0)
{
break;
}
remaining -= nr;
}
return n - remaining;
}
/**
 * 主函数
 * @param args
 */
public static void main(String args[])
{
consult();
try
{
isidx.close();
isdict.close();
}
catch (Exception e)
{
System.out.println("Close files error!");
e.printStackTrace();
}
}
}

如果要在windows平台下编译http://blog.chinaunix.net/uid-20454005-id-1675913.html文章中的程序代码最好保存为cpp文件以C++项目编译执行,而且strcasecmp函数应该换为stricmp函数,并且上面作者原来的程序是在linux平台下的,字符编码本身就是UTF8的不需要进行编码转换,但在windows平台下中文为gb232编码,就需要进行编码的转换,下面为需要添加修改上的字符编码转换后的程序。

//UTF-8到GB2312的转换

       char* U2G(const char* utf8)

       {

              int len = MultiByteToWideChar(CP_UTF8, 0, utf8, -1, NULL, 0);

              wchar_t* wstr = new wchar_t[len+1];

              memset(wstr, 0, len+1);

              MultiByteToWideChar(CP_UTF8, 0, utf8, -1, wstr, len);

              len = WideCharToMultiByte(CP_ACP, 0, wstr, -1, NULL, 0, NULL, NULL);

              char* str = new char[len+1];

              memset(str, 0, len+1);

              WideCharToMultiByte(CP_ACP, 0, wstr, -1, str, len, NULL, NULL);

              if(wstr) delete[] wstr;

              return str;

       }

 

       //GB2312到UTF-8的转换

       char* G2U(const char* gb2312)

       {

              int len = MultiByteToWideChar(CP_ACP, 0, gb2312, -1, NULL, 0);

              wchar_t* wstr = new wchar_t[len+1];

              memset(wstr, 0, len+1);

              MultiByteToWideChar(CP_ACP, 0, gb2312, -1, wstr, len);

              len = WideCharToMultiByte(CP_UTF8, 0, wstr, -1, NULL, 0, NULL, NULL);

              char* str = new char[len+1];

              memset(str, 0, len+1);

              WideCharToMultiByte(CP_UTF8, 0, wstr, -1, str, len, NULL, NULL);

              if(wstr) delete[] wstr;

              return str;

       }

      

 

       /*

       * 显示data内容

       */

       void display_data(char *data_buf, unsigned int data_length)

       {

              fwrite(data_buf,data_length,1,stdout);

 

              char *data=(char *)malloc(data_length);

              memcpy(data,data_buf,data_length);

              char *p=U2G(data_buf);

              printf("%s\n",p);

              free(data);

              delete p;

       }

以星际译王所支持的牛津英汉词典oxford-gb作为测试,词典格式为UTF8编码的单词字符串,然后是四个字节的int型数据表示该单词在dict释义文件中的起始偏移量,再后四个字节的int型数据表示dict文件中该单词释义总共的长度,如下图所示:

结果显示能够正确得到单词的释义,只是音标未能正确解码,如下图所示:

 

本文中的测试程序和文件下载地址:

JAVA版http://download.csdn.net/detail/menglongbor/4947295

VC++版http://download.csdn.net/detail/menglongbor/5007550

星际译王中实际上采用的是另外的方法来缓存单词的索引,并使用了二分查找来实现快速查找单词释义,同时针对单词的查询设计了模糊查询、单词词根、后缀等方法搜寻相近单词的释义,更多关于星际译王的词典格式和实现可以参考胡正的《星际译王-自由软件讲座》讲义。如果需要自行编辑词典可以使用星际译王中的stardict-editor工具来编辑。

----------------星际译王---------------

最新3.03版本去如下站点下载安装:

http://code.google.com/p/stardict-3/downloads/list

http://www.stardict.org/

http://www.huzheng.org/

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
【Stardict的词库现在官方已经无法下载了, 网站上许多转载的词库下载都是直接连接官方之前公布的下载连接, 这些地址已经失效, 目前能直接下载到词库的只有少数的论坛或者FTP.】 星际译王(StarDict)在Linux, Windows, 甚至Mac OS X上都相应的本, 因为其开源的缘故, 许多智能手机(iPhone, 黑莓, Maemo, Meego, Symbian, WM)都有移植读取Stardict词库的手机词典. 这词库我自己本人在用的 ---------------部分词典列表----------------------- English 6M. English_German 5M. German_English 7.8M. English_French 5.4M. French_English 3.6M. English_Spanish 4.7M. Spanish_English 5.8M. English_Italian 4.7M. Italian_English 3.2M. English_Dutch 4.5M. Dutch_English 2.1M. English_Portuguese 5M. Portuguese_English 3.8M. English_Hebrew 5.2M. Hebrew_English 2.4M. Hebrew_Thesaurus 3.6M. English_Japanese 5M. Japanese_English 9.7M. English_Chinese_S_ 2.1M. Chinese_S_English 1.9M. English_Chinese_T_ 1.8M. Chinese_T_English 1.9M. English_Russian 3.2M. Russian_English 4.5M. English_Turkish 2.4M. Turkish_English 5.6M. English_Swedish 3.4M. Greek_English 1.5M. English_Greek 1.4M. English-Korean 2M. Korean-English 3.4M. English-Arabic 1.5M. Arabic-English 2.5M. English dictionaries American Heritage Dictionary, 4th Edition 12M. American Heritage Dictionary, 4th Edition - With image 59M. Britannica Concise Encyclopedia 16M. Britannica Pocket Encyclopedia 11M. Oxford Advanced learner's Dictionary 4M. Oxford Talking Dictionary 31M. Cambridge Advanced Learner's Dictionary 6M. Collins COBUILD Advanced Learner's English Dictionary 5.9M. Collins COBUILD V3 7M. Collins COBUILD English Dictionary 6M. WordNet 2.0 13M. Shorter Oxford English Dictionary (Fifth Edition) 24M. Longman Dictionary of Contemporary English (4th Ed) 8M. Longman Dictionary of Contemporary English (4th Ed)w image 28M. American Idioms 780K. Concise Oxford English Dictionary 7M. Concise Oxford Thesaurus 3M. Merriam-Webster Collegiate® Dictionary 33M. Merriam-Webster Collegiate® Thesaurus 2M. Britannica.com 9M. CIA World Factbook 2005 5M. FOLDOC 2.6M. Acronyms from A - Z 1.5M. Most Common Acronyms and Abbreviations 145K. MacMillan English Dictionary -American 5M. Chinese dictionaries 牛津高阶英汉双解词典 13M. 牛津现代英汉双解词典 6M. Kingsoft English-Chinese Bilingual Dictionary 15M. Longman English-Chinese Computer Dictionary 673K. 高级汉语大词典 6M. 现代汉语词典 3M. URX ZHEN Chinese-English dictionary 6M. 计算机网络与移动通信 276K. 家庭实用菜谱 28M. Windows术语表 119K. 超级数字大词典 576K. German dictionaries Fachlexikon der Sozialen Marktwirtschaft (ChinLex) 78K. ChinLex - Fachw?rterbuch Wirtschaft Deutsch-Chinesisch (S) - Image version 874K. Deutsch-Interlingua Wörterbuch 1M. English-German Online Dictionary 1.1M. Duden Deutsch-Deutsch Lexikon 7M. Fundset Deutsch2Chinese(S) 4M. 新德汉词典 2.7M. fundset KDIC decn 596K. German-Chinese V2.27 739K. German-English Online Dictionaries 1.1M. SAP - Glossary German - English 79K. SAP - Glossary English - German 78K. WAHRIG.digital - Deutsches Wörterbuch 11M. Handwörterbuch Englisch-Deutsch 4M. Handwörterbuch Deutsch-Englisch 6.6M. Technik Englisch-Deutsch 6M. Technik Deutsch-Englisch 6.5M. Wirtschaft Englisch-Deutsch 1.7M. Wirtschaft Deutsch-Englisch 1.9M. Japanese dictionaries 知恵蔵2005 3M. Genius English-Japanese 10M. Genius Japanese-English 9M. Japanese-Chinese 7.6M. 会社四季報 2005年1集 7M. Meikyo Japanese-Japanese 8M. マイペディア 18M. 南山堂医学大辞典 49M. Health dictionaries Baydaş_Medikal Terimler 2004 794K Dictionary of Medicine (Shahram) 420K Drug information 196K Medciclopedia 1.6M Medicine English-Arabic 1.7M Pharmaceutical terms 38K Misc dictionaries Interlingua-English 1M. Larousse Chambers français-anglais 7.6M. Larousse Chambers English-French 9M. Larousse Multidico 19M. Mas_NDon English Indonesian Dictionary 2M. Mas_NDon Indonesian to English Dictionary 1.3M. Balifolder.com 546K. Indonesian-English Online Dictionaries 342K.
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值