大学IT网 - 最懂大学生的IT学习网站! QQ资料交流群:367606806
当前位置:大学IT网 > Java技巧 > JAVA版StarDict星际译王简单实现

JAVA版StarDict星际译王简单实现

关键词:JavaJAVA版StarDict星际译王简单实现  阅读(638) 赞(12)

[摘要]本文主要是对JAVA版StarDict星际译王简单实现的讲解,希望对大家学习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文件中该单词释义总共的长度,如下图所示:

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



相关评论