java实现汉字字典

环境:eclipsse, jdk1.6, 没有使用第三方的包,都是JDK有的。

注意,项目源文件我都使用的是UTF-8的编码格式,如果不是,代码里面的汉字注释会显示乱码。

设置UTF-8:windows->Preferences->General->Workspace 页面上Text file encoding,选择Other UTF-8

项目结构:

1.字典文件

dic.txt 下载地址:http://download.csdn.net/detail/wssiqi/5056993

这里只摘录一部分内容,里面共收录了20902个汉字

[plain] view
plain
 copy

  1. 19968,一,一,1,1,GGLL,A,yi1,yī
  2. 19969,丁,一,2,12,SGH,AI,ding1,dīng,zheng1,zhēng
  3. 19970,丂,一,2,15,GNV,AZVV,kao3,kǎo,qiao3,qiǎo,yu2,yú
  4. 19971,七,一,2,15,AGN,HD,qi1,qī
  5. 19972,丄,一,2,21,HGD,IAVV,shang4,shàng
  6. 19973,丅,一,2,12,GHK,AIAA,xia4,xià
  7. 19974,丆,一,2,13,DGT,GDAA,han3,hǎn
  8. 19975,万,一,3,153,DNV,,wan4,wàn,mo4,mò
  9. 19976,丈,一,3,134,DYI,AOS,zhang4,zhàng
  10. 19977,三,一,3,111,DGGG,CD,san1,sān
  11. 19978,上,一,3,211,HHGG,IDA,shang3,shǎng,shang4,shàng
  12. 19979,下,一,3,124,GHI,AID,xia4,xià
  13. 19980,丌,一,3,132,GJK,AND,ji1,jī,qi2,qí
  14. 19981,不,一,4,1324,GII,GI,fou3,fǒu,bu4,bù
  15. 19982,与,一,3,151,GNGD,AZA,yu4,yù,yu3,yǔ,yu2,yú
  16. 19983,丏,一,4,1255,GHNN,AIZY,mian3,miǎn
  17. 19984,丐,一,4,1215,GHNV,AIZ,gai4,gài
  18. 19985,丑,一,4,5211,NFD,XED,chou3,chǒu
  19. 19986,丒,一,4,5341,VYGF,YDSA,chou3,chǒu

2.Dic.java

[java] view
plain
 copy

  1. package com.siqi.dict;
  2. import java.io.BufferedReader;
  3. import java.io.ByteArrayInputStream;
  4. import java.io.File;
  5. import java.io.FileInputStream;
  6. import java.io.InputStreamReader;
  7. import java.nio.charset.Charset;
  8. /**
  9. * 汉字本地字典。 <br/>
  10. * 本地字典数据来自于<a href=http://www.zdic.net/search/?c=2>汉典</a>
  11. * 实现了一下常用的需求,例如返回拼音,五笔,拼音首字母,笔画数目,笔画顺序。
  12. *
  13. * @author siqi
  14. *
  15. */
  16. public class Dic {
  17. /**
  18. * 设置是否输出调试信息
  19. */
  20. private static boolean DEBUG = true;
  21. /**
  22. * 默认编码
  23. */
  24. public static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8");
  25. /**
  26. * 汉字Unicode最小编码
  27. */
  28. public static final int CN_U16_CODE_MIN = 0x4e00;
  29. /**
  30. * 汉字Unicode最大编码
  31. */
  32. public static final int CN_U16_CODE_MAX = 0x9fa5;
  33. /**
  34. * 本地字典文件名
  35. */
  36. public static final String DIC_FILENAME = "dic.txt";
  37. /**
  38. * 字典数据
  39. */
  40. public static byte[] bytes = new byte[0];
  41. /**
  42. * 字典汉字数目
  43. */
  44. public static int count = 0;
  45. /**
  46. * 汉字unicode值在一条汉字信息的位置<br/>
  47. * 汉字信息,例:"25171,打,扌,5,12112,RSH,DAI,da3,dǎ,da2,dá"
  48. */
  49. public static int INDEX_UNICODE = 0;
  50. /**
  51. * 汉字在一条汉字信息的位置<br/>
  52. * 汉字信息,例:"25171,打,扌,5,12112,RSH,DAI,da3,dǎ,da2,dá"
  53. */
  54. public static int INDEX_CHARACTER = 1;
  55. /**
  56. * 汉字部首在一条汉字信息的位置<br/>
  57. * 汉字信息,例:"25171,打,扌,5,12112,RSH,DAI,da3,dǎ,da2,dá"
  58. */
  59. public static int INDEX_BUSHOU = 2;
  60. /**
  61. * 汉字笔画在一条汉字信息的位置<br/>
  62. * 汉字信息,例:"25171,打,扌,5,12112,RSH,DAI,da3,dǎ,da2,dá"
  63. */
  64. public static int INDEX_BIHUA = 3;
  65. /**
  66. * 汉字笔画顺序在一条汉字信息的位置<br/>
  67. * 汉字信息,例:"25171,打,扌,5,12112,RSH,DAI,da3,dǎ,da2,dá"
  68. */
  69. public static int INDEX_BISHUN = 4;
  70. /**
  71. * 汉字五笔在一条汉字信息的位置<br/>
  72. * 汉字信息,例:"25171,打,扌,5,12112,RSH,DAI,da3,dǎ,da2,dá"
  73. */
  74. public static int INDEX_WUBI = 5;
  75. /**
  76. * 汉字郑码在一条汉字信息的位置<br/>
  77. * 汉字信息,例:"25171,打,扌,5,12112,RSH,DAI,da3,dǎ,da2,dá"
  78. */
  79. public static int INDEX_ZHENGMA = 6;
  80. /**
  81. * 第一个汉字拼音(英文字母)在一条汉字信息的位置<br/>
  82. * 汉字信息,例:"25171,打,扌,5,12112,RSH,DAI,da3,dǎ,da2,dá"
  83. */
  84. public static int INDEX_PINYIN_EN = 7;
  85. /**
  86. * 第一个汉字拼音(中文字母)在一条汉字信息的位置<br/>
  87. * 汉字信息,例:"25171,打,扌,5,12112,RSH,DAI,da3,dǎ,da2,dá"
  88. */
  89. public static int INDEX_PINYIN_CN = 8;
  90. /**
  91. * 装载字典
  92. */
  93. static {
  94. long time = System.currentTimeMillis();
  95. try {
  96. LoadDictionary();
  97. count = count();
  98. if (DEBUG) {
  99. System.out.println("成功载入字典" + new File(DIC_FILENAME).getCanonicalPath() + " ,用时:"
  100. + (System.currentTimeMillis() - time) + "毫秒,载入字符数"+count);
  101. }
  102. } catch (Exception e) {
  103. try {
  104. System.out.println("载入字典失败" + new File(DIC_FILENAME).getCanonicalPath()+"\r\n");
  105. } catch (Exception e1) {
  106. }
  107. e.printStackTrace();
  108. }
  109. }
  110. /**
  111. * 获取汉字unicode值
  112. *
  113. * @param ch
  114. *            汉字
  115. * @return 返回汉字的unicode值
  116. * @throws Exception
  117. */
  118. public static String GetUnicode(Character ch) throws Exception {
  119. return GetCharInfo(ch, INDEX_UNICODE);
  120. }
  121. /**
  122. * 获取拼音(英文字母)
  123. *
  124. * @param ch
  125. *            单个汉字字符
  126. * @return 返回汉字的英文字母拼音。如 "大"->"da4"。
  127. * @throws Exception
  128. */
  129. public static String GetPinyinEn(Character ch) throws Exception {
  130. return GetCharInfo(ch, INDEX_PINYIN_EN);
  131. }
  132. /**
  133. * 返回汉字字符串的拼音(英文字母)
  134. *
  135. * @param str
  136. *            汉字字符串
  137. * @return 返回汉字字符串的拼音。将字符串中的汉字替换成拼音,其他字符不变。拼音中间会有空格。 注意,对于多音字,返回的拼音可能不正确。
  138. * @throws Exception
  139. */
  140. public static String GetPinyinEn(String str) throws Exception {
  141. StringBuffer sb = new StringBuffer();
  142. for (int i = 0; i < str.length(); i++) {
  143. char ch = str.charAt(i);
  144. if (isChineseChar(ch)) {
  145. sb.append(GetPinyinEn(ch) + " ");
  146. } else {
  147. sb.append(ch);
  148. }
  149. }
  150. return sb.toString().trim();
  151. }
  152. /**
  153. * 获取拼音(中文字母)
  154. *
  155. * @param ch
  156. *            单个汉字字符
  157. * @return 返回汉字的中文字母拼音。如 "打"->"dǎ"。
  158. * @throws Exception
  159. */
  160. public static String GetPinyinCn(Character ch) throws Exception {
  161. return GetCharInfo(ch, INDEX_PINYIN_CN);
  162. }
  163. /**
  164. * 返回汉字字符串的拼音(中文字母)
  165. *
  166. * @param str
  167. *            汉字字符串
  168. * @return 返回汉字字符串的拼音。将字符串中的汉字替换成拼音,其他字符不变。拼音中间会有空格。 注意,对于多音字,返回的拼音可能不正确。
  169. * @throws Exception
  170. */
  171. public static String GetPinyinCn(String str) throws Exception {
  172. StringBuffer sb = new StringBuffer();
  173. for (int i = 0; i < str.length(); i++) {
  174. char ch = str.charAt(i);
  175. if (isChineseChar(ch)) {
  176. sb.append(GetPinyinCn(ch) + " ");
  177. } else {
  178. sb.append(ch);
  179. }
  180. }
  181. return sb.toString().trim();
  182. }
  183. /**
  184. * 返回拼音首字母
  185. *
  186. * @param ch
  187. * @return
  188. * @throws Exception
  189. */
  190. public static String GetFirstLetter(Character ch) throws Exception {
  191. if (isChineseChar(ch)) {
  192. return GetPinyinEn(ch).substring(0, 1);
  193. } else {
  194. return "";
  195. }
  196. }
  197. /**
  198. * 返回汉字字符串拼音首字母,如果不是汉字,会被忽略掉。
  199. *
  200. * @param str
  201. *            汉字字符串
  202. * @return
  203. * @throws Exception
  204. */
  205. public static String GetFirstLetter(String str) throws Exception {
  206. StringBuffer sb = new StringBuffer();
  207. for (int i = 0; i < str.length(); i++) {
  208. char ch = str.charAt(i);
  209. if (isChineseChar(ch)) {
  210. sb.append(GetFirstLetter(ch));
  211. }
  212. }
  213. return sb.toString().trim();
  214. }
  215. /**
  216. * 获取汉字部首
  217. *
  218. * @param ch
  219. *            汉字
  220. * @return 返回汉字的部首
  221. * @throws Exception
  222. */
  223. public static String GetBushou(Character ch) throws Exception {
  224. return GetCharInfo(ch, INDEX_BUSHOU);
  225. }
  226. /**
  227. * 获取汉字笔画数目
  228. *
  229. * @param ch
  230. *            汉字
  231. * @return 返回汉字的笔画数目
  232. * @throws Exception
  233. */
  234. public static String GetBihua(Character ch) throws Exception {
  235. return GetCharInfo(ch, INDEX_BIHUA);
  236. }
  237. /**
  238. * 获取汉字笔画顺序
  239. *
  240. * @param ch
  241. *            汉字
  242. * @return 返回汉字的笔画顺序
  243. * @throws Exception
  244. */
  245. public static String GetBishun(Character ch) throws Exception {
  246. return GetCharInfo(ch, INDEX_BISHUN);
  247. }
  248. /**
  249. * 获取汉字五笔
  250. *
  251. * @param ch
  252. *            汉字
  253. * @return 返回汉字五笔
  254. * @throws Exception
  255. */
  256. public static String GetWubi(Character ch) throws Exception {
  257. return GetCharInfo(ch, INDEX_WUBI);
  258. }
  259. /**
  260. * 获取汉字郑码
  261. *
  262. * @param ch
  263. *            汉字
  264. * @return 返回汉字郑码
  265. * @throws Exception
  266. */
  267. public static String GetZhengma(Character ch) throws Exception {
  268. return GetCharInfo(ch, INDEX_ZHENGMA);
  269. }
  270. /**
  271. * 从字典中获取汉字信息
  272. *
  273. * @param ch
  274. *            要查询的汉字
  275. * @return 返回汉字信息,如"25171,打,扌,5,12112,RSH,DAI,da3,dǎ,da2,dá" <br/>
  276. *         第一是汉字unicode值<br/>
  277. *         第二是汉字<br/>
  278. *         第三是汉字部首<br/>
  279. *         第四是汉字笔画<br/>
  280. *         第五是汉字笔画顺序("12345"分别代表"横竖撇捺折")<br/>
  281. *         第六是汉字五笔<br/>
  282. *         第七是汉字郑码<br/>
  283. *         第八及以后是汉字的拼音(英文字母拼音和中文字母拼音)<br/>
  284. * @throws Exception
  285. */
  286. public static String GetCharInfo(Character ch) throws Exception {
  287. if (!isChineseChar(ch)) {
  288. throw new Exception("‘" + ch + "‘ 不是一个汉字!");
  289. }
  290. String result = "";
  291. ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
  292. BufferedReader br = new BufferedReader(new InputStreamReader(bais));
  293. String strWord;
  294. while ((strWord = br.readLine()) != null) {
  295. if (strWord.startsWith(String.valueOf(ch.hashCode()))) {
  296. result = strWord;
  297. break;
  298. }
  299. }
  300. br.close();
  301. bais.close();
  302. return result;
  303. }
  304. /**
  305. * 返回汉字信息
  306. *
  307. * @param ch
  308. *            汉字
  309. * @param index
  310. *            信息所在的Index
  311. * @return
  312. * @throws Exception
  313. */
  314. private static String GetCharInfo(Character ch, int index) throws Exception {
  315. if (!isChineseChar(ch)) {
  316. throw new Exception("‘" + ch + "‘ 不是一个汉字!");
  317. }
  318. // 获取汉字信息
  319. String charInfo = GetCharInfo(ch);
  320. String result = "";
  321. try {
  322. result = charInfo.split(",")[index];
  323. } catch (Exception e) {
  324. throw new Exception("请查看字典中" + ch + "汉字记录是否正确!");
  325. }
  326. return result;
  327. }
  328. /**
  329. * 载入字典文件到内存。
  330. * @throws Exception
  331. */
  332. private static void LoadDictionary() throws Exception {
  333. File file = new File(DIC_FILENAME);
  334. bytes = new byte[(int) file.length()];
  335. FileInputStream fis = new FileInputStream(file);
  336. fis.read(bytes, 0, bytes.length);
  337. fis.close();
  338. }
  339. /**
  340. * 判断字符是否为汉字,在测试的时候,我发现汉字的字符的hashcode值 跟汉字Unicode
  341. * 16的值一样,所以可以用hashcode来判断是否为汉字。
  342. *
  343. * @param ch
  344. *            汉字
  345. * @return 是汉字返回true,否则返回false。
  346. */
  347. public static boolean isChineseChar(Character ch) {
  348. if (ch.hashCode() >= CN_U16_CODE_MIN
  349. && ch.hashCode() <= CN_U16_CODE_MAX) {
  350. return true;
  351. } else {
  352. return false;
  353. }
  354. }
  355. /**
  356. *
  357. * @return 返回字典包含的汉字数目。
  358. * @throws Exception
  359. */
  360. private static int count() throws Exception {
  361. int cnt = 0;
  362. ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
  363. BufferedReader br = new BufferedReader(new InputStreamReader(bais));
  364. while (br.readLine() != null) {
  365. cnt++;
  366. }
  367. br.close();
  368. bais.close();
  369. return cnt;
  370. }
  371. }

3.Sample.java

如何使用字典

[java] view
plain
 copy

  1. package com.siqi.dict;
  2. /**
  3. * 包含两个实例,示例如何获取汉字的拼音等信息。
  4. * @author siqi
  5. *
  6. */
  7. public class Sample {
  8. /**
  9. * 字典使用实例
  10. *
  11. * @param args
  12. */
  13. public static void main(String[] args) {
  14. try {
  15. long time = System.currentTimeMillis();
  16. char ch = ‘打‘;
  17. //汉字单个字符
  18. System.out.println("====打字信息开始====");
  19. System.out.println("首字母:"+Dic.GetFirstLetter(ch));
  20. System.out.println("拼音(中):"+Dic.GetPinyinCn(ch));
  21. System.out.println("拼音(英):"+Dic.GetPinyinEn(ch));
  22. System.out.println("部首:"+Dic.GetBushou(ch));
  23. System.out.println("笔画数目:"+Dic.GetBihua(ch));
  24. System.out.println("笔画:"+Dic.GetBishun(ch));
  25. System.out.println("五笔:"+Dic.GetWubi(ch));
  26. System.out.println("====打字信息结束====");
  27. //汉字字符串
  28. System.out.println("\r\n====汉字字符串====");
  29. System.out.println(Dic.GetPinyinEn("返回汉字字符串的拼音。"));
  30. System.out.println(Dic.GetPinyinCn("返回汉字字符串的拼音。"));
  31. System.out.println(Dic.GetFirstLetter("返回汉字字符串的拼音。"));
  32. System.out.println("====汉字字符串====\r\n");
  33. System.out.println("用时:"+(System.currentTimeMillis()-time)+"毫秒");
  34. } catch (Exception e) {
  35. e.printStackTrace();
  36. }
  37. }
  38. }

4.结果

[html] view
plain
 copy

  1. ====打字信息开始====
  2. 成功载入字典C:\workspaces\01_java\DictLocal\dic.txt ,用时:15毫秒,载入字符数20902
  3. 首字母:d
  4. 拼音(中):dǎ
  5. 拼音(英):da3
  6. 部首:扌
  7. 笔画数目:5
  8. 笔画:12112
  9. 五笔:RSH
  10. ====打字信息结束====
  11. ====汉字字符串====
  12. fan3 hui2 han4 zi4 zi4 fu2 chuan4 di2 pin1 yin1 。
  13. fǎn huí hàn zì zì fú chuàn dí pīn yīn 。
  14. fhhzzfcdpy
  15. ====汉字字符串====
  16. Memory(Used/Total) : 1539/15872 KB
  17. 用时:218毫秒

待会再上传如何获取字典文件的,我是通过收集http://www.zdic.net/zd/的网页来获取的

=============补充,如何获取汉字的信息================

=============所有的信息都是从汉典网站上获取的=========

目录结构为:

环境:eclipsse, jdk1.6, 没有使用第三方的包,都是JDK有的。

注意,项目源文件我都使用的是UTF-8的编码格式,如果不是,代码里面的汉字注释会显示乱码。

设置UTF-8:windows->Preferences->General->Workspace 页面上Text file encoding,选择Other UTF-8

包说明:

com.siqi.http

Httpclient.Java是我写的一个简单的获取网页的类,用来获取网页内容;

com.siqi.dict

DictMain.java用来下载汉字网页,从中获取汉字的拼音信息,并保存到data.dat中

DownloadThread.java用来下载网页(多线程)

com.siqi.pinyin

PinYin.java在执行过DictMain.java后,会生成一个data.dat,把这个文件拷贝到com.siqi.pinyin包下面,就可以调用PinYin.java里面的函数得到汉字的拼音了

PinYinEle.java一个汉字->拼音->Unicode的模型

源码:

Httpclient.java 可以用来获取网页,可以的到网页内容,网页编码和网页的header,简版

[java] view
plain
 copy

  1. package com.siqi.http;
  2. import java.io.IOException;
  3. import java.io.InputStream;
  4. import java.net.Socket;
  5. import java.net.URLEncoder;
  6. import java.util.regex.Matcher;
  7. import java.util.regex.Pattern;
  8. /**
  9. * 使用SOCKET实现简单的网页GET和POST
  10. *
  11. * @author siqi
  12. *
  13. */
  14. public class Httpclient {
  15. /**
  16. * processUrl 参数 HTTP GET
  17. */
  18. public static final int METHOD_GET = 0;
  19. /**
  20. * processUrl 参数 HTTP POST
  21. */
  22. public static final int METHOD_POST = 1;
  23. /**
  24. * HTTP GET的报头,简化版
  25. */
  26. public static final String HEADER_GET = "GET %s HTTP/1.0\r\nHOST: %s\r\n\r\n";
  27. /**
  28. * HTTP POST的报头,简化版
  29. */
  30. public static final String HEADER_POST = "POST %s HTTP/1.0\r\nHOST: %s\r\nContent-Length: 0\r\n\r\n";
  31. /**
  32. * 网页报头和内容的分割符
  33. */
  34. public static final String CONTENT_SEPARATOR = "\r\n\r\n";
  35. /**
  36. * 网页请求响应内容byte
  37. */
  38. private byte[] bytes = new byte[0];
  39. /**
  40. * 网页报头
  41. */
  42. private String header = "";
  43. /**
  44. * 网页内容
  45. */
  46. private String content = "";
  47. /**
  48. * 网页编码,默认为UTF-8
  49. */
  50. public static final String CHARSET_DEFAULT = "UTF-8";
  51. /**
  52. * 网页编码
  53. */
  54. private String charset = CHARSET_DEFAULT;
  55. /**
  56. * 使用Httpclient的例子
  57. *
  58. * @param args
  59. * @throws Exception
  60. */
  61. public static void main(String[] args) throws Exception {
  62. Httpclient httpclient = new Httpclient();
  63. // 请求百度首页(手机版)
  64. httpclient.processUrl("http://m.baidu.com/");
  65. System.out.println("获取网页http://m.baidu.com/");
  66. System.out.println("报头为:\r\n" + httpclient.getHeader());
  67. System.out.println("内容为:\r\n" + httpclient.getContent());
  68. System.out.println("编码为:\r\n" + httpclient.getCharset());
  69. System.out.println("************************************");
  70. // 使用百度搜索"中国"(手机版)
  71. // 这是手机百度搜索框的源码 <input id="word" type="text" size="20" maxlength="64"
  72. // name="word">
  73. String url = String.format("http://m.baidu.com/s?word=%s",
  74. URLEncoder.encode("中国", CHARSET_DEFAULT));
  75. httpclient.processUrl(url, METHOD_POST);
  76. System.out.println("获取网页http://m.baidu.com/s?word=中国");
  77. System.out.println("报头为:\r\n" + httpclient.getHeader());
  78. System.out.println("内容为:\r\n" + httpclient.getContent());
  79. System.out.println("编码为:\r\n" + httpclient.getCharset());
  80. }
  81. /**
  82. * 初始化,设置所有变量为默认值
  83. */
  84. private void init() {
  85. this.bytes = new byte[0];
  86. this.charset = CHARSET_DEFAULT;
  87. this.header = "";
  88. this.content = "";
  89. }
  90. /**
  91. * 获取网页报头header
  92. *
  93. * @return
  94. */
  95. public String getHeader() {
  96. return header;
  97. }
  98. /**
  99. * 获取网页内容content
  100. *
  101. * @return
  102. */
  103. public String getContent() {
  104. return content;
  105. }
  106. /**
  107. * 获取网页编码
  108. *
  109. * @return
  110. */
  111. public String getCharset() {
  112. return charset;
  113. }
  114. /**
  115. * 请求网页内容(使用HTTP GET)
  116. *
  117. * @param url
  118. * @throws Exception
  119. */
  120. public void processUrl(String url) throws Exception {
  121. processUrl(url, METHOD_GET);
  122. }
  123. /**
  124. * 使用Socket请求(获取)一个网页。<br/>
  125. * 例如:<br/>
  126. * processUrl("http://www.baidu.com/", METHOD_GET)会获取百度首页;<br/>
  127. *
  128. * @param url
  129. *            这个网页或者网页内容的地址
  130. * @param method
  131. *            请求网页的方法: METHOD_GET或者METHOD_POST
  132. * @throws Exception
  133. */
  134. public void processUrl(String url, int method) throws Exception {
  135. init();
  136. // url = "http://www.zdic.net/search/?c=2&q=%E5%A4%A7";
  137. // 规范化链接,当网址为http://www.baidu.com时,将网址变为:http://www.baidu.com/
  138. Matcher mat = Pattern.compile("https?://[^/]+").matcher(url);
  139. if (mat.find() && mat.group().equals(url)) {
  140. url += "/";
  141. }
  142. Socket socket = new Socket(getHostUrl(url), 80); // 设置要连接的服务器地址
  143. socket.setSoTimeout(3000); // 设置超时时间为3秒
  144. String request = null;
  145. // 构造请求,详情请参考HTTP协议(RFC2616)
  146. if (method == METHOD_POST) {
  147. request = String.format(HEADER_POST, getSubUrl(url),
  148. getHostUrl(url));
  149. } else {
  150. request = String
  151. .format(HEADER_GET, getSubUrl(url), getHostUrl(url));
  152. }
  153. socket.getOutputStream().write(request.getBytes());// 发送请求
  154. this.bytes = InputStream2ByteArray(socket.getInputStream());// 读取响应
  155. // 获取网页编码,我们只需要测试查找前4096个字节,一般编码信息都会在里面找到
  156. String temp = new String(this.bytes, 0,
  157. bytes.length < 4096 ? bytes.length : 4096);
  158. mat = Pattern.compile("(?<=<meta.{0,100}?charset=)[a-z-0-9]*",
  159. Pattern.CASE_INSENSITIVE).matcher(temp);
  160. if (mat.find()) {
  161. this.charset = mat.group();
  162. } else {
  163. this.charset = CHARSET_DEFAULT;
  164. }
  165. // 用正确的编码得到网页报头和内容
  166. temp = new String(this.bytes, this.charset);
  167. int headerEnd = temp.indexOf(CONTENT_SEPARATOR);
  168. this.header = temp.substring(0, headerEnd);
  169. this.content = temp.substring(headerEnd + CONTENT_SEPARATOR.length(),
  170. temp.length());
  171. socket.close(); // 关闭socket
  172. }
  173. /**
  174. * 根据网址,获取服务器地址<br/>
  175. * 例如:<br/>
  176. * http://m.weathercn.com/common/province.jsp
  177. * <p>
  178. * 返回:<br/>
  179. * m.weathercn.com
  180. *
  181. * @param url
  182. *            网址
  183. * @return
  184. */
  185. public static String getHostUrl(String url) {
  186. String host = "";
  187. Matcher mat = Pattern.compile("(?<=https?://).+?(?=/)").matcher(url);
  188. if (mat.find()) {
  189. host = mat.group();
  190. }
  191. return host;
  192. }
  193. /**
  194. * 根据网址,获取网页路径 例如:<br/>
  195. * http://m.weathercn.com/common/province.jsp
  196. * <p>
  197. * 返回:<br/>
  198. * /common/province.jsp
  199. *
  200. * @param url
  201. * @return 如果没有获取到网页路径,返回"";
  202. */
  203. public static String getSubUrl(String url) {
  204. String subUrl = "";
  205. Matcher mat = Pattern.compile("https?://.+?(?=/)").matcher(url);
  206. if (mat.find()) {
  207. subUrl = url.substring(mat.group().length());
  208. }
  209. return subUrl;
  210. }
  211. /**
  212. * 将b1和b2两个byte数组拼接成一个, 结果=b1+b2
  213. *
  214. * @param b1
  215. * @param b2
  216. * @return
  217. */
  218. public static byte[] ByteArrayCat(byte[] b1, byte[] b2) {
  219. byte[] b = new byte[b1.length + b2.length];
  220. System.arraycopy(b1, 0, b, 0, b1.length);
  221. System.arraycopy(b2, 0, b, b1.length, b2.length);
  222. return b;
  223. }
  224. /**
  225. * 读取输入流并转为byte数组,不返回字符串, 是因为输入流的编码不确定,错误的编码会造成乱码。
  226. *
  227. * @param is
  228. *            输入流inputstream
  229. * @return 字符串
  230. * @throws IOException
  231. */
  232. public static byte[] InputStream2ByteArray(InputStream is)
  233. throws IOException {
  234. byte[] b = new byte[0];
  235. byte[] bb = new byte[4096]; // 缓冲区
  236. int len = 0;
  237. while ((len = is.read(bb)) != -1) {
  238. byte[] newb = new byte[b.length + len];
  239. System.arraycopy(b, 0, newb, 0, b.length);
  240. System.arraycopy(bb, 0, newb, b.length, len);
  241. b = newb;
  242. }
  243. return b;
  244. }
  245. }

DictMain.java

[java] view
plain
 copy

  1. package com.siqi.dict;
  2. import java.io.File;
  3. import java.io.FileReader;
  4. import java.io.FileWriter;
  5. import java.io.IOException;
  6. import java.util.regex.Matcher;
  7. import java.util.regex.Pattern;
  8. /**
  9. * 从汉典下载汉字网页,并提取拼音信息
  10. * @author siqi
  11. *
  12. */
  13. public class DictMain {
  14. /**
  15. * 网页保存路径
  16. */
  17. public static final String SAVEPATH = "dict/pages/";
  18. /**
  19. * 下载的汉字网页名称
  20. */
  21. public static final String FILEPATH = SAVEPATH + "%s.html";
  22. /**
  23. * 字典数据文件名称
  24. */
  25. public static final String DATA_FILENAME = "data.txt";
  26. /**
  27. * 汉字unicode最小
  28. */
  29. public static final int UNICODE_MIN = 0x4E00;
  30. /**
  31. * 汉字unicode最大
  32. */
  33. public static final int UNICODE_MAX = 0x9FFF;
  34. /**
  35. * 准备工作:
  36. * 1.从汉典网站下载所有汉字的页面,注意,不要在eclipse中打开保存页面的文件夹,
  37. * 因为每个汉字一个页面,总共有20000+个页面,容易卡死eclipse
  38. * 2.从汉字页面获取汉字拼音信息,生成data.dat文件
  39. * 3.生成的data.dat复制到com.siqi.pinyin下面
  40. * 4.可以使用com.siqi.pinyin.PinYin.java了
  41. */
  42. static{
  43. // 下载网页
  44. for (int i = UNICODE_MIN; i <= UNICODE_MAX; i++) {
  45. // 检查是否已经存在
  46. String filePath = String.format(FILEPATH, i); // 文件名
  47. File file = new File(filePath);
  48. if (!file.exists()) {
  49. new DownloadThread(i).start();
  50. }
  51. }
  52. //解析网页,得到拼音信息,并保存到data.dat
  53. StringBuffer sb = new StringBuffer();
  54. for (int i = UNICODE_MIN; i <= UNICODE_MAX; i++) {
  55. String word = new String(Character.toChars(i));
  56. String pinyin = getPinYinFromWebpageFile(String.format(FILEPATH, i));
  57. String str = String.format("%s,%s,%s\r\n", i,word,pinyin);
  58. System.out.print(str);
  59. sb.append(str);
  60. }
  61. //保存到data.dat
  62. try {
  63. FileWriter fw = new FileWriter(DATA_FILENAME);
  64. fw.write(sb.toString());
  65. fw.close();
  66. } catch (IOException e) {
  67. e.printStackTrace();
  68. }
  69. }
  70. public static void main(String[] args){
  71. System.out.println("All prepared!");
  72. }
  73. /**
  74. * 从网页文件获取拼音信息
  75. * @param file
  76. * @return
  77. */
  78. private static String getPinYinFromWebpageFile(String file) {
  79. try {
  80. char[] buff = new char[(int) new File(file).length()];
  81. FileReader reader = new FileReader(file);
  82. reader.read(buff);
  83. reader.close();
  84. String content = new String(buff);
  85. // spf("yi1")
  86. Matcher mat = Pattern.compile("(?<=spf\\(\")[a-z1-4]{0,100}",
  87. Pattern.CASE_INSENSITIVE).matcher(content);
  88. if (mat.find()) {
  89. return mat.group();
  90. }
  91. //<span class="dicpy">cal</span> spf("xin1")
  92. mat = Pattern.compile("(?<=class=\"dicpy\">)[a-z1-4]{0,100}",
  93. Pattern.CASE_INSENSITIVE).matcher(content);
  94. if (mat.find()) {
  95. return mat.group();
  96. }
  97. } catch (Exception e) {
  98. e.printStackTrace();
  99. }
  100. return "";
  101. }
  102. }

DownloadThread.java

[java] view
plain
 copy

  1. package com.siqi.dict;
  2. import java.io.File;
  3. import java.io.FileWriter;
  4. import java.net.URLEncoder;
  5. import java.util.regex.Matcher;
  6. import java.util.regex.Pattern;
  7. import com.siqi.http.Httpclient;
  8. /**
  9. * 将汉字页面从汉典网站下载下来,存储到本地
  10. * http://www.zdic.net/search/?c=2
  11. * @author siqi
  12. *
  13. */
  14. public class DownloadThread extends Thread{
  15. /**
  16. * 线程最大数目
  17. */
  18. public static int THREAD_MAX = 10;
  19. /**
  20. * 下载最大重复次数
  21. */
  22. public static int RETRY_MAX = 5;
  23. /**
  24. * 汉典网站搜索网址
  25. */
  26. public static String SEARCH_URL = "http://www.zdic.net/search/?q=%s";
  27. /**
  28. * 当前线程数目
  29. */
  30. private static int threadCnt = 0;
  31. /**
  32. * 当前线程处理汉字的unicode编码
  33. */
  34. private int unicode = 0;
  35. /**
  36. * 如果PATH文件夹不存在,那么创建它
  37. */
  38. static{
  39. try {
  40. File file = new File(DictMain.SAVEPATH);
  41. if (!file.exists()) {
  42. file.mkdirs();
  43. }
  44. } catch (Exception e) {
  45. }
  46. }
  47. /**
  48. * 返回当前线程数量
  49. * @param i 修改当前线程数量 threadCnt += i;
  50. * @return 返回修改后线程数量
  51. */
  52. public static synchronized int threadCnt(int i){
  53. threadCnt += i;
  54. return threadCnt;
  55. }
  56. /**
  57. * 下载UNICODE编码为unicode的汉字网页
  58. * @param unicode
  59. */
  60. public DownloadThread(int unicode){
  61. //等待,直到当前线程数量小于THREAD_MAX
  62. while(threadCnt(0)>THREAD_MAX){
  63. try {
  64. Thread.sleep(500);
  65. } catch (InterruptedException e) {
  66. }
  67. }
  68. threadCnt(1);   //线程数量+1
  69. this.unicode = unicode;
  70. }
  71. @Override
  72. public void run() {
  73. long t1 = System.currentTimeMillis(); // 记录时间
  74. String filePath = String.format(DictMain.FILEPATH, unicode); // 文件名
  75. String word = new String(Character.toChars(unicode)); // 将unicode转换为数字
  76. boolean downloaded = false;
  77. int retryCnt = 0; // 下载失败重复次数
  78. while (!downloaded && retryCnt < RETRY_MAX) {
  79. try {
  80. String content = DownloadPage(word);
  81. SaveToFile(filePath, content);
  82. downloaded = true;
  83. threadCnt(-1);
  84. System.out.println(String.format("%s, %s, 下载成功!线程数目:%s 用时:%s",
  85. unicode, word, threadCnt(0), System.currentTimeMillis()
  86. - t1));
  87. return;
  88. } catch (Exception e) {
  89. retryCnt++;
  90. }
  91. }
  92. threadCnt(-1);
  93. System.err.println(String.format("%s, %s, 下载失败!线程数目:%s 用时:%s", unicode,
  94. word, threadCnt(0), System.currentTimeMillis() - t1));
  95. }
  96. /**
  97. * 在汉典网站上查找汉字,返回汉字字典页面内容
  98. * @param word
  99. * @return
  100. * @throws Exception
  101. */
  102. public String DownloadPage(String word) throws Exception{
  103. //查找word
  104. Httpclient httpclient = new Httpclient();
  105. String url = String.format(SEARCH_URL, URLEncoder.encode(word, "UTF-8"));
  106. httpclient.processUrl(url, Httpclient.METHOD_POST);
  107. //返回的是一个跳转页
  108. //获取跳转的链接
  109. Matcher mat = Pattern.compile("(?<=HREF=\")[^\"]+").matcher(httpclient.getContent());
  110. if(mat.find()){
  111. httpclient.processUrl(mat.group());
  112. }
  113. return httpclient.getContent();
  114. }
  115. /**
  116. * 将内容content写入file文件
  117. * @param file
  118. * @param content
  119. */
  120. public void SaveToFile(String file, String content){
  121. try {
  122. FileWriter fw = new FileWriter(file);
  123. fw.write(content);
  124. fw.close();
  125. } catch (Exception e) {
  126. e.printStackTrace();
  127. }
  128. }
  129. }

PinYin.java

[java] view
plain
 copy

  1. package com.siqi.pinyin;
  2. import java.io.BufferedReader;
  3. import java.io.InputStreamReader;
  4. import java.util.HashMap;
  5. import java.util.Map;
  6. public class PinYin {
  7. private static Map<Integer, PinYinEle> map = new HashMap<Integer, PinYinEle>();
  8. /**
  9. * 载入pinyin数据文件
  10. */
  11. static {
  12. try {
  13. BufferedReader bReader = new BufferedReader(new InputStreamReader(
  14. PinYin.class.getResourceAsStream("data.dat")));
  15. String aLine = null;
  16. while ((aLine = bReader.readLine()) != null) {
  17. PinYinEle ele = new PinYinEle(aLine);
  18. map.put(ele.getUnicode(), ele);
  19. }
  20. bReader.close();
  21. } catch (Exception e) {
  22. e.printStackTrace();
  23. }
  24. }
  25. /**
  26. * 去掉注释可以测试一下
  27. *
  28. * @param args
  29. */
  30. public static void main(String[] args) {
  31. System.out.println(" 包含声调:" + PinYin.getPinYin("大家haome12345"));
  32. System.out.println("不包含声调:" + PinYin.getPinYin("大家haome12345", false));
  33. }
  34. /**
  35. * 获取汉字字符串的拼音,containsNumber是否获取拼音中的声调1、2、3、4
  36. *
  37. * @param str
  38. * @param containsNumber
  39. *            true = 包含声调,false = 不包含声调
  40. * @return
  41. */
  42. public static String getPinYin(String str, boolean containsNumber) {
  43. StringBuffer sb = new StringBuffer();
  44. for (Character ch : str.toCharArray()) {
  45. sb.append(getPinYin(ch, containsNumber));
  46. }
  47. return sb.toString();
  48. }
  49. /**
  50. * 获取字符串的拼音
  51. *
  52. * @param str
  53. * @return
  54. */
  55. public static String getPinYin(String str) {
  56. StringBuffer sb = new StringBuffer();
  57. for (Character ch : str.toCharArray()) {
  58. sb.append(getPinYin(ch));
  59. }
  60. return sb.toString();
  61. }
  62. /**
  63. * 获取单个汉字的拼音,包含声调
  64. *
  65. * @param ch
  66. * @return
  67. */
  68. public static String getPinYin(Character ch) {
  69. return getPinYin(ch, true);
  70. }
  71. /**
  72. * 获取单个汉字的拼音
  73. *
  74. * @param ch
  75. *            汉字. 如果输入非汉字,返回ch. 如果输入null,返回空字符串;
  76. * @param containsNumber
  77. *            true = 包含声调,false = 不包含声调
  78. * @return
  79. */
  80. public static String getPinYin(Character ch, boolean containsNumber) {
  81. if (ch != null) {
  82. int code = ch.hashCode();
  83. if (map.containsKey(code)) {
  84. if (containsNumber) {
  85. return map.get(code).getPinyin();
  86. } else {
  87. return map.get(code).getPinyin().replaceAll("[0-9]", "");
  88. }
  89. } else {
  90. return ch.toString();
  91. }
  92. }
  93. return "";
  94. }
  95. }

PinYinEle.java

[java] view
plain
 copy

  1. package com.siqi.pinyin;
  2. public class PinYinEle {
  3. private int unicode;
  4. private String ch;
  5. private String pinyin;
  6. public PinYinEle(){}
  7. public PinYinEle(String str){
  8. if(str!=null){
  9. String[] strs = str.split(",");
  10. if(strs.length == 3){
  11. try{
  12. this.unicode = Integer.parseInt(strs[0]);
  13. }catch(Exception e){
  14. }
  15. this.ch = strs[1];
  16. this.pinyin = strs[2];
  17. }
  18. }
  19. }
  20. public int getUnicode() {
  21. return unicode;
  22. }
  23. public void setUnicode(int unicode) {
  24. this.unicode = unicode;
  25. }
  26. public String getCh() {
  27. return ch;
  28. }
  29. public void setCh(String ch) {
  30. this.ch = ch;
  31. }
  32. public String getPinyin() {
  33. return pinyin;
  34. }
  35. public void setPinyin(String pinyin) {
  36. this.pinyin = pinyin;
  37. }
  38. }

生成的data.dat里面内容(部分)为:

[java] view
plain
 copy

  1. 19968,一,yi1
  2. 19969,丁,ding1
  3. 19970,丂,kao3
  4. 19971,七,qi1
  5. 19972,丄,shang4
  6. 19973,丅,xia4
  7. 19974,丆,han3
  8. 19975,万,wan4
  9. 19976,丈,zhang4
  10. 19977,三,san1
  11. 19978,上,shang4
  12. 19979,下,xia4
  13. 19980,丌,qi2
  14. 19981,不,bu4

运行DictMain.java结果

执行时间可能会有几十分钟到几小时不等,总共会下载200+M的网页(20000+个网页),每次运行都会先判断以前下载过没有,所以结束掉程序不会有影响

显示All prepared!表示已经准备好了,刷新项目文件夹,可以看到网页保持在dict/pages下面,不建议在elipse中打开那个文件夹,因为里面有2万多个文件,会卡死eclipse,

还可以看到生成了data.txt文件,改为data.dat并复制到pinyin文件夹下面

运行PinYin.java

可以看到"大家haome12345"的拼音:

[java] view
plain
 copy

  1. 包含声调:da4jia1haome12345
  2. 包含声调:dajiahaome12345

上面只是显示了如何获取拼音,获取笔画等的方法类似,在这里就不演示了。

时间: 2024-10-10 10:49:16

java实现汉字字典的相关文章

java保存汉字到mysal乱码

java存数据到mysql java保存前汉字正常显示,到mysql乱码 直接在小海豚上(sqlyog)修改,网上很多人都说在dos里写语句神马的,弄了一圈也不管用,还麻烦,最后发现直接工具就能修改 1,该数据库 2.表 把字符集改为utf8就可以了 3.如果还不行,至多把mysql安装文件下my.ini文件里default-character-set = utf8和character-set-server = utf8修改了就可以了 4.完事 java保存汉字到mysal乱码,布布扣,bubu

java将汉字转成拼音

package com.jframe.kit; import net.sourceforge.pinyin4j.PinyinHelper; import net.sourceforge.pinyin4j.format.HanyuPinyinCaseType; import net.sourceforge.pinyin4j.format.HanyuPinyinOutputFormat; import net.sourceforge.pinyin4j.format.HanyuPinyinToneTy

Java 解析汉字拼音

需要java包 :pinyin4j-2.5.0.jar pinyin4j的使用很方便,一般转换只需要使用PinyinHelper类的静态工具方法即可: String[] pinyin = PinyinHelper.toHanyuPinyinStringArray('赵'); //该类还有其他的拼音转换形式,但是基本上用不到,就不介绍了 返回的数组即是该字符的拼音,如上例就是pinyin[0]=zhao,后面的数字代表声调,声调为5表示轻读,无声调.之所谓返回数组,是因为被判定的汉字有可能有多个读

Java一个汉字占几个字节(详解与原理)(转载)

1.先说重点: 不同的编码格式占字节数是不同的,UTF-8编码下一个中文所占字节也是不确定的,可能是2个.3个.4个字节: 2.以下是源码: 1 @Test 2 public void test1() throws UnsupportedEncodingException { 3 String a = "名"; 4 System.out.println("UTF-8编码长度:"+a.getBytes("UTF-8").length); 5 Sys

JAVA 中汉字在不同编码下的字节不同

*/ utf-8中文字节长度:6 utf-16中文字节长度:6 UTF-16BE中文字节长度:4 UTF-16LE中文字节长度:4 UTF-32中文字节长度:8 UTF-32BE中文字节长度:8 UTF-32LE中文字节长度:8 unicode中文字节长度:6 GBK中文字节长度:4 GB2312中文字节长度:4 GB18030中文字节长度:4 ISO8859-1中文字节长度:2 BIG5中文字节长度:3 ASCII中文字节长度:2 -------------------------------

java获取汉字拼音首字母 --转载

在项目中要更能根据某些查询条件(比如姓名)的首字母作为条件进行查询,比如查一个叫"李晓明"的人,可以输入'lxm'.写了一个工具类如下: import java.io.UnsupportedEncodingException; /** * 取得给定汉字串的首字母串,即声母串 * Title: ChineseCharToEn * @date 2004-02-19 注:只支持GB2312字符集中的汉字 */ public final class ChineseCharToEn { priv

java验证码-汉字验证码

今天整理了一个java实现的汉字输入验证码 主要包含两个类,一个是生成验证码,一个是判断验证码输入是否正确 实现原理非常简单,将汉字和干扰线生成图片并将汉字保存到session,前台获取每次生成验证码图片并用文本框值和session值比较,功能就怎么简单. 生成汉字验证码源码展示 1 package xwcms.net.service; 2 import java.awt.Color; 3 import java.awt.Font; 4 import java.awt.Graphics; 5 i

Java中将汉字转为拼音

首先,加入pinyin4j-2.5.0.jar包,jar包在源码中有 写工具类 public class PingYinUtil {       /**       * 将字符串中的中文转化为拼音,其他字符不变       *        * @param inputString       * @return       */       public static String getPingYin(String inputString) {           HanyuPinyinOu

adnroid java 获取汉字 字母的首拼音,全拼音,大写首拼音

给打大家提供一个获取汉字字母的首拼音,全拼音,首大写的几个方法: 这里需要用到一个外库,pinyin4j-2.5.0.jar大家可以自己上网下载或者找我分享: 这个也给有做分享pinyin4j-2.5.0.jar:外库可以直接下载 底下是对库的使用,几个使用的例子: //"首拼音大写" public static String getAlpha(String chines) {  String pinyinName = "";  char[] nameChar =