最新的可以下载的包(原来写的丢失了,重新写了个):
http://download.csdn.net/detail/wssiqi/6394057
如果地址不可访问,查看我的资源,看还在不。~~~
环境: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个汉字
19968,一,一,1,1,GGLL,A,yi1,yī
19969,丁,一,2,12,SGH,AI,ding1,dīng,zheng1,zhēng
19970,丂,一,2,15,GNV,AZVV,kao3,kǎo,qiao3,qiǎo,yu2,yú
19971,七,一,2,15,AGN,HD,qi1,qī
19972,丄,一,2,21,HGD,IAVV,shang4,shàng
19973,丅,一,2,12,GHK,AIAA,xia4,xià
19974,丆,一,2,13,DGT,GDAA,han3,hǎn
19975,万,一,3,153,DNV,,wan4,wàn,mo4,mò
19976,丈,一,3,134,DYI,AOS,zhang4,zhàng
19977,三,一,3,111,DGGG,CD,san1,sān
19978,上,一,3,211,HHGG,IDA,shang3,shǎng,shang4,shàng
19979,下,一,3,124,GHI,AID,xia4,xià
19980,丌,一,3,132,GJK,AND,ji1,jī,qi2,qí
19981,不,一,4,1324,GII,GI,fou3,fǒu,bu4,bù
19982,与,一,3,151,GNGD,AZA,yu4,yù,yu3,yǔ,yu2,yú
19983,丏,一,4,1255,GHNN,AIZY,mian3,miǎn
19984,丐,一,4,1215,GHNV,AIZ,gai4,gài
19985,丑,一,4,5211,NFD,XED,chou3,chǒu
19986,丒,一,4,5341,VYGF,YDSA,chou3,chǒu
2.Dic.java
package com.siqi.dict;import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.nio.charset.Charset;/*** 汉字本地字典。 <br/>* 本地字典数据来自于<a href=http://www.zdic.net/search/?c=2>汉典</a>* 实现了一下常用的需求,例如返回拼音,五笔,拼音首字母,笔画数目,笔画顺序。* * @author siqi* */
public class Dic {/*** 设置是否输出调试信息*/private static boolean DEBUG = true;/*** 默认编码*/public static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8");/*** 汉字Unicode最小编码*/public static final int CN_U16_CODE_MIN = 0x4e00;/*** 汉字Unicode最大编码*/public static final int CN_U16_CODE_MAX = 0x9fa5;/*** 本地字典文件名*/public static final String DIC_FILENAME = "dic.txt";/*** 字典数据*/public static byte[] bytes = new byte[0];/*** 字典汉字数目*/public static int count = 0;/*** 汉字unicode值在一条汉字信息的位置<br/>* 汉字信息,例:"25171,打,扌,5,12112,RSH,DAI,da3,dǎ,da2,dá"*/public static int INDEX_UNICODE = 0;/*** 汉字在一条汉字信息的位置<br/>* 汉字信息,例:"25171,打,扌,5,12112,RSH,DAI,da3,dǎ,da2,dá"*/public static int INDEX_CHARACTER = 1;/*** 汉字部首在一条汉字信息的位置<br/>* 汉字信息,例:"25171,打,扌,5,12112,RSH,DAI,da3,dǎ,da2,dá"*/public static int INDEX_BUSHOU = 2;/*** 汉字笔画在一条汉字信息的位置<br/>* 汉字信息,例:"25171,打,扌,5,12112,RSH,DAI,da3,dǎ,da2,dá"*/public static int INDEX_BIHUA = 3;/*** 汉字笔画顺序在一条汉字信息的位置<br/>* 汉字信息,例:"25171,打,扌,5,12112,RSH,DAI,da3,dǎ,da2,dá"*/public static int INDEX_BISHUN = 4;/*** 汉字五笔在一条汉字信息的位置<br/>* 汉字信息,例:"25171,打,扌,5,12112,RSH,DAI,da3,dǎ,da2,dá"*/public static int INDEX_WUBI = 5;/*** 汉字郑码在一条汉字信息的位置<br/>* 汉字信息,例:"25171,打,扌,5,12112,RSH,DAI,da3,dǎ,da2,dá"*/public static int INDEX_ZHENGMA = 6;/*** 第一个汉字拼音(英文字母)在一条汉字信息的位置<br/>* 汉字信息,例:"25171,打,扌,5,12112,RSH,DAI,da3,dǎ,da2,dá"*/public static int INDEX_PINYIN_EN = 7;/*** 第一个汉字拼音(中文字母)在一条汉字信息的位置<br/>* 汉字信息,例:"25171,打,扌,5,12112,RSH,DAI,da3,dǎ,da2,dá"*/public static int INDEX_PINYIN_CN = 8;/*** 装载字典*/static {long time = System.currentTimeMillis();try {LoadDictionary();count = count();if (DEBUG) {System.out.println("成功载入字典" + new File(DIC_FILENAME).getCanonicalPath() + " ,用时:"+ (System.currentTimeMillis() - time) + "毫秒,载入字符数"+count);}} catch (Exception e) {try {System.out.println("载入字典失败" + new File(DIC_FILENAME).getCanonicalPath()+"\r\n");} catch (Exception e1) {}e.printStackTrace();}}/*** 获取汉字unicode值* * @param ch* 汉字* @return 返回汉字的unicode值* @throws Exception*/public static String GetUnicode(Character ch) throws Exception {return GetCharInfo(ch, INDEX_UNICODE);}/*** 获取拼音(英文字母)* * @param ch* 单个汉字字符* @return 返回汉字的英文字母拼音。如 "大"->"da4"。* @throws Exception*/public static String GetPinyinEn(Character ch) throws Exception {return GetCharInfo(ch, INDEX_PINYIN_EN);}/*** 返回汉字字符串的拼音(英文字母)* * @param str* 汉字字符串* @return 返回汉字字符串的拼音。将字符串中的汉字替换成拼音,其他字符不变。拼音中间会有空格。 注意,对于多音字,返回的拼音可能不正确。* @throws Exception*/public static String GetPinyinEn(String str) throws Exception {StringBuffer sb = new StringBuffer();for (int i = 0; i < str.length(); i++) {char ch = str.charAt(i);if (isChineseChar(ch)) {sb.append(GetPinyinEn(ch) + " ");} else {sb.append(ch);}}return sb.toString().trim();}/*** 获取拼音(中文字母)* * @param ch* 单个汉字字符* @return 返回汉字的中文字母拼音。如 "打"->"dǎ"。* @throws Exception*/public static String GetPinyinCn(Character ch) throws Exception {return GetCharInfo(ch, INDEX_PINYIN_CN);}/*** 返回汉字字符串的拼音(中文字母)* * @param str* 汉字字符串* @return 返回汉字字符串的拼音。将字符串中的汉字替换成拼音,其他字符不变。拼音中间会有空格。 注意,对于多音字,返回的拼音可能不正确。* @throws Exception*/public static String GetPinyinCn(String str) throws Exception {StringBuffer sb = new StringBuffer();for (int i = 0; i < str.length(); i++) {char ch = str.charAt(i);if (isChineseChar(ch)) {sb.append(GetPinyinCn(ch) + " ");} else {sb.append(ch);}}return sb.toString().trim();}/*** 返回拼音首字母* * @param ch* @return* @throws Exception*/public static String GetFirstLetter(Character ch) throws Exception {if (isChineseChar(ch)) {return GetPinyinEn(ch).substring(0, 1);} else {return "";}}/*** 返回汉字字符串拼音首字母,如果不是汉字,会被忽略掉。* * @param str* 汉字字符串* @return* @throws Exception*/public static String GetFirstLetter(String str) throws Exception {StringBuffer sb = new StringBuffer();for (int i = 0; i < str.length(); i++) {char ch = str.charAt(i);if (isChineseChar(ch)) {sb.append(GetFirstLetter(ch));}}return sb.toString().trim();}/*** 获取汉字部首* * @param ch* 汉字* @return 返回汉字的部首* @throws Exception*/public static String GetBushou(Character ch) throws Exception {return GetCharInfo(ch, INDEX_BUSHOU);}/*** 获取汉字笔画数目* * @param ch* 汉字* @return 返回汉字的笔画数目* @throws Exception*/public static String GetBihua(Character ch) throws Exception {return GetCharInfo(ch, INDEX_BIHUA);}/*** 获取汉字笔画顺序* * @param ch* 汉字* @return 返回汉字的笔画顺序* @throws Exception*/public static String GetBishun(Character ch) throws Exception {return GetCharInfo(ch, INDEX_BISHUN);}/*** 获取汉字五笔* * @param ch* 汉字* @return 返回汉字五笔* @throws Exception*/public static String GetWubi(Character ch) throws Exception {return GetCharInfo(ch, INDEX_WUBI);}/*** 获取汉字郑码* * @param ch* 汉字* @return 返回汉字郑码* @throws Exception*/public static String GetZhengma(Character ch) throws Exception {return GetCharInfo(ch, INDEX_ZHENGMA);}/*** 从字典中获取汉字信息* * @param ch* 要查询的汉字* @return 返回汉字信息,如"25171,打,扌,5,12112,RSH,DAI,da3,dǎ,da2,dá" <br/>* 第一是汉字unicode值<br/>* 第二是汉字<br/>* 第三是汉字部首<br/>* 第四是汉字笔画<br/>* 第五是汉字笔画顺序("12345"分别代表"横竖撇捺折")<br/>* 第六是汉字五笔<br/>* 第七是汉字郑码<br/>* 第八及以后是汉字的拼音(英文字母拼音和中文字母拼音)<br/>* @throws Exception*/public static String GetCharInfo(Character ch) throws Exception {if (!isChineseChar(ch)) {throw new Exception("'" + ch + "' 不是一个汉字!");}String result = "";ByteArrayInputStream bais = new ByteArrayInputStream(bytes);BufferedReader br = new BufferedReader(new InputStreamReader(bais));String strWord;while ((strWord = br.readLine()) != null) {if (strWord.startsWith(String.valueOf(ch.hashCode()))) {result = strWord;break;}}br.close();bais.close();return result;}/*** 返回汉字信息* * @param ch* 汉字* @param index* 信息所在的Index* @return* @throws Exception*/private static String GetCharInfo(Character ch, int index) throws Exception {if (!isChineseChar(ch)) {throw new Exception("'" + ch + "' 不是一个汉字!");}// 获取汉字信息String charInfo = GetCharInfo(ch);String result = "";try {result = charInfo.split(",")[index];} catch (Exception e) {throw new Exception("请查看字典中" + ch + "汉字记录是否正确!");}return result;}/*** 载入字典文件到内存。* @throws Exception */private static void LoadDictionary() throws Exception {File file = new File(DIC_FILENAME);bytes = new byte[(int) file.length()];FileInputStream fis = new FileInputStream(file);fis.read(bytes, 0, bytes.length);fis.close();}/*** 判断字符是否为汉字,在测试的时候,我发现汉字的字符的hashcode值 跟汉字Unicode* 16的值一样,所以可以用hashcode来判断是否为汉字。* * @param ch* 汉字* @return 是汉字返回true,否则返回false。*/public static boolean isChineseChar(Character ch) {if (ch.hashCode() >= CN_U16_CODE_MIN&& ch.hashCode() <= CN_U16_CODE_MAX) {return true;} else {return false;}}/*** * @return 返回字典包含的汉字数目。* @throws Exception*/private static int count() throws Exception {int cnt = 0;ByteArrayInputStream bais = new ByteArrayInputStream(bytes);BufferedReader br = new BufferedReader(new InputStreamReader(bais));while (br.readLine() != null) {cnt++;}br.close();bais.close();return cnt;}
}
3.Sample.java
如何使用字典
package com.siqi.dict;/*** 包含两个实例,示例如何获取汉字的拼音等信息。* @author siqi**/
public class Sample {/*** 字典使用实例* * @param args*/public static void main(String[] args) {try {long time = System.currentTimeMillis();char ch = '打';//汉字单个字符System.out.println("====打字信息开始====");System.out.println("首字母:"+Dic.GetFirstLetter(ch));System.out.println("拼音(中):"+Dic.GetPinyinCn(ch));System.out.println("拼音(英):"+Dic.GetPinyinEn(ch));System.out.println("部首:"+Dic.GetBushou(ch));System.out.println("笔画数目:"+Dic.GetBihua(ch));System.out.println("笔画:"+Dic.GetBishun(ch));System.out.println("五笔:"+Dic.GetWubi(ch));System.out.println("====打字信息结束====");//汉字字符串System.out.println("\r\n====汉字字符串====");System.out.println(Dic.GetPinyinEn("返回汉字字符串的拼音。"));System.out.println(Dic.GetPinyinCn("返回汉字字符串的拼音。"));System.out.println(Dic.GetFirstLetter("返回汉字字符串的拼音。"));System.out.println("====汉字字符串====\r\n");System.out.println("用时:"+(System.currentTimeMillis()-time)+"毫秒");} catch (Exception e) {e.printStackTrace();}}
}
4.结果
====打字信息开始====
成功载入字典C:\workspaces\01_java\DictLocal\dic.txt ,用时:15毫秒,载入字符数20902
首字母:d
拼音(中):dǎ
拼音(英):da3
部首:扌
笔画数目:5
笔画:12112
五笔:RSH
====打字信息结束========汉字字符串====
fan3 hui2 han4 zi4 zi4 fu2 chuan4 di2 pin1 yin1 。
fǎn huí hàn zì zì fú chuàn dí pīn yīn 。
fhhzzfcdpy
====汉字字符串====Memory(Used/Total) : 1539/15872 KB
用时: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.httpHttpclient.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,简版
package com.siqi.http;import java.io.IOException;
import java.io.InputStream;
import java.net.Socket;
import java.net.URLEncoder;
import java.util.regex.Matcher;
import java.util.regex.Pattern;/*** 使用SOCKET实现简单的网页GET和POST* * @author siqi* */
public class Httpclient {/*** processUrl 参数 HTTP GET*/public static final int METHOD_GET = 0;/*** processUrl 参数 HTTP POST*/public static final int METHOD_POST = 1;/*** HTTP GET的报头,简化版*/public static final String HEADER_GET = "GET %s HTTP/1.0\r\nHOST: %s\r\n\r\n";/*** HTTP POST的报头,简化版*/public static final String HEADER_POST = "POST %s HTTP/1.0\r\nHOST: %s\r\nContent-Length: 0\r\n\r\n";/*** 网页报头和内容的分割符*/public static final String CONTENT_SEPARATOR = "\r\n\r\n";/*** 网页请求响应内容byte*/private byte[] bytes = new byte[0];/*** 网页报头*/private String header = "";/*** 网页内容*/private String content = "";/*** 网页编码,默认为UTF-8*/public static final String CHARSET_DEFAULT = "UTF-8";/*** 网页编码*/private String charset = CHARSET_DEFAULT;/*** 使用Httpclient的例子* * @param args* @throws Exception*/public static void main(String[] args) throws Exception {Httpclient httpclient = new Httpclient();// 请求百度首页(手机版)httpclient.processUrl("http://m.baidu.com/");System.out.println("获取网页http://m.baidu.com/");System.out.println("报头为:\r\n" + httpclient.getHeader());System.out.println("内容为:\r\n" + httpclient.getContent());System.out.println("编码为:\r\n" + httpclient.getCharset());System.out.println("************************************");// 使用百度搜索"中国"(手机版)// 这是手机百度搜索框的源码 <input id="word" type="text" size="20" maxlength="64"// name="word">String url = String.format("http://m.baidu.com/s?word=%s",URLEncoder.encode("中国", CHARSET_DEFAULT));httpclient.processUrl(url, METHOD_POST);System.out.println("获取网页http://m.baidu.com/s?word=中国");System.out.println("报头为:\r\n" + httpclient.getHeader());System.out.println("内容为:\r\n" + httpclient.getContent());System.out.println("编码为:\r\n" + httpclient.getCharset());}/*** 初始化,设置所有变量为默认值*/private void init() {this.bytes = new byte[0];this.charset = CHARSET_DEFAULT;this.header = "";this.content = "";}/*** 获取网页报头header* * @return*/public String getHeader() {return header;}/*** 获取网页内容content* * @return*/public String getContent() {return content;}/*** 获取网页编码* * @return*/public String getCharset() {return charset;}/*** 请求网页内容(使用HTTP GET)* * @param url* @throws Exception*/public void processUrl(String url) throws Exception {processUrl(url, METHOD_GET);}/*** 使用Socket请求(获取)一个网页。<br/>* 例如:<br/>* processUrl("http://www.baidu.com/", METHOD_GET)会获取百度首页;<br/>* * @param url* 这个网页或者网页内容的地址* @param method* 请求网页的方法: METHOD_GET或者METHOD_POST* @throws Exception*/public void processUrl(String url, int method) throws Exception {init();// url = "http://www.zdic.net/search/?c=2&q=%E5%A4%A7";// 规范化链接,当网址为http://www.baidu.com时,将网址变为:http://www.baidu.com/Matcher mat = Pattern.compile("https?://[^/]+").matcher(url);if (mat.find() && mat.group().equals(url)) {url += "/";}Socket socket = new Socket(getHostUrl(url), 80); // 设置要连接的服务器地址socket.setSoTimeout(3000); // 设置超时时间为3秒String request = null;// 构造请求,详情请参考HTTP协议(RFC2616)if (method == METHOD_POST) {request = String.format(HEADER_POST, getSubUrl(url),getHostUrl(url));} else {request = String.format(HEADER_GET, getSubUrl(url), getHostUrl(url));}socket.getOutputStream().write(request.getBytes());// 发送请求this.bytes = InputStream2ByteArray(socket.getInputStream());// 读取响应// 获取网页编码,我们只需要测试查找前4096个字节,一般编码信息都会在里面找到String temp = new String(this.bytes, 0,bytes.length < 4096 ? bytes.length : 4096);mat = Pattern.compile("(?<=<meta.{0,100}?charset=)[a-z-0-9]*",Pattern.CASE_INSENSITIVE).matcher(temp);if (mat.find()) {this.charset = mat.group();} else {this.charset = CHARSET_DEFAULT;}// 用正确的编码得到网页报头和内容temp = new String(this.bytes, this.charset);int headerEnd = temp.indexOf(CONTENT_SEPARATOR);this.header = temp.substring(0, headerEnd);this.content = temp.substring(headerEnd + CONTENT_SEPARATOR.length(),temp.length());socket.close(); // 关闭socket}/*** 根据网址,获取服务器地址<br/>* 例如:<br/>* http://m.weathercn.com/common/province.jsp* <p>* 返回:<br/>* m.weathercn.com* * @param url* 网址* @return*/public static String getHostUrl(String url) {String host = "";Matcher mat = Pattern.compile("(?<=https?://).+?(?=/)").matcher(url);if (mat.find()) {host = mat.group();}return host;}/*** 根据网址,获取网页路径 例如:<br/>* http://m.weathercn.com/common/province.jsp* <p>* 返回:<br/>* /common/province.jsp* * @param url* @return 如果没有获取到网页路径,返回"";*/public static String getSubUrl(String url) {String subUrl = "";Matcher mat = Pattern.compile("https?://.+?(?=/)").matcher(url);if (mat.find()) {subUrl = url.substring(mat.group().length());}return subUrl;}/*** 将b1和b2两个byte数组拼接成一个, 结果=b1+b2* * @param b1* @param b2* @return*/public static byte[] ByteArrayCat(byte[] b1, byte[] b2) {byte[] b = new byte[b1.length + b2.length];System.arraycopy(b1, 0, b, 0, b1.length);System.arraycopy(b2, 0, b, b1.length, b2.length);return b;}/*** 读取输入流并转为byte数组,不返回字符串, 是因为输入流的编码不确定,错误的编码会造成乱码。* * @param is* 输入流inputstream* @return 字符串* @throws IOException*/public static byte[] InputStream2ByteArray(InputStream is)throws IOException {byte[] b = new byte[0];byte[] bb = new byte[4096]; // 缓冲区int len = 0;while ((len = is.read(bb)) != -1) {byte[] newb = new byte[b.length + len];System.arraycopy(b, 0, newb, 0, b.length);System.arraycopy(bb, 0, newb, b.length, len);b = newb;}return b;}
}
DictMain.java
package com.siqi.dict;import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.regex.Matcher;
import java.util.regex.Pattern;/*** 从汉典下载汉字网页,并提取拼音信息* @author siqi**/
public class DictMain {/*** 网页保存路径*/public static final String SAVEPATH = "dict/pages/";/*** 下载的汉字网页名称*/public static final String FILEPATH = SAVEPATH + "%s.html";/*** 字典数据文件名称*/public static final String DATA_FILENAME = "data.txt";/*** 汉字unicode最小*/public static final int UNICODE_MIN = 0x4E00;/*** 汉字unicode最大*/public static final int UNICODE_MAX = 0x9FFF;/*** 准备工作:* 1.从汉典网站下载所有汉字的页面,注意,不要在eclipse中打开保存页面的文件夹,* 因为每个汉字一个页面,总共有20000+个页面,容易卡死eclipse* 2.从汉字页面获取汉字拼音信息,生成data.dat文件* 3.生成的data.dat复制到com.siqi.pinyin下面* 4.可以使用com.siqi.pinyin.PinYin.java了*/static{// 下载网页for (int i = UNICODE_MIN; i <= UNICODE_MAX; i++) {// 检查是否已经存在String filePath = String.format(FILEPATH, i); // 文件名File file = new File(filePath);if (!file.exists()) {new DownloadThread(i).start();}}//解析网页,得到拼音信息,并保存到data.datStringBuffer sb = new StringBuffer();for (int i = UNICODE_MIN; i <= UNICODE_MAX; i++) {String word = new String(Character.toChars(i));String pinyin = getPinYinFromWebpageFile(String.format(FILEPATH, i));String str = String.format("%s,%s,%s\r\n", i,word,pinyin);System.out.print(str);sb.append(str);}//保存到data.dattry {FileWriter fw = new FileWriter(DATA_FILENAME);fw.write(sb.toString());fw.close();} catch (IOException e) {e.printStackTrace();}}public static void main(String[] args){System.out.println("All prepared!");}/*** 从网页文件获取拼音信息* @param file* @return*/private static String getPinYinFromWebpageFile(String file) {try {char[] buff = new char[(int) new File(file).length()];FileReader reader = new FileReader(file);reader.read(buff);reader.close();String content = new String(buff);// spf("yi1")Matcher mat = Pattern.compile("(?<=spf\\(\")[a-z1-4]{0,100}",Pattern.CASE_INSENSITIVE).matcher(content);if (mat.find()) {return mat.group();}//<span class="dicpy">cal</span> spf("xin1")mat = Pattern.compile("(?<=class=\"dicpy\">)[a-z1-4]{0,100}",Pattern.CASE_INSENSITIVE).matcher(content);if (mat.find()) {return mat.group();}} catch (Exception e) {e.printStackTrace();}return "";}
}
DownloadThread.java
package com.siqi.dict;import java.io.File;
import java.io.FileWriter;
import java.net.URLEncoder;
import java.util.regex.Matcher;
import java.util.regex.Pattern;import com.siqi.http.Httpclient;/*** 将汉字页面从汉典网站下载下来,存储到本地* http://www.zdic.net/search/?c=2* @author siqi**/
public class DownloadThread extends Thread{/*** 线程最大数目*/public static int THREAD_MAX = 10;/*** 下载最大重复次数*/public static int RETRY_MAX = 5;/*** 汉典网站搜索网址*/public static String SEARCH_URL = "http://www.zdic.net/search/?q=%s";/*** 当前线程数目*/private static int threadCnt = 0;/*** 当前线程处理汉字的unicode编码*/private int unicode = 0;/*** 如果PATH文件夹不存在,那么创建它*/static{try {File file = new File(DictMain.SAVEPATH);if (!file.exists()) {file.mkdirs();}} catch (Exception e) {}}/*** 返回当前线程数量* @param i 修改当前线程数量 threadCnt += i;* @return 返回修改后线程数量*/public static synchronized int threadCnt(int i){threadCnt += i;return threadCnt;}/*** 下载UNICODE编码为unicode的汉字网页* @param unicode*/public DownloadThread(int unicode){//等待,直到当前线程数量小于THREAD_MAXwhile(threadCnt(0)>THREAD_MAX){try {Thread.sleep(500);} catch (InterruptedException e) {}}threadCnt(1); //线程数量+1this.unicode = unicode;}@Overridepublic void run() {long t1 = System.currentTimeMillis(); // 记录时间String filePath = String.format(DictMain.FILEPATH, unicode); // 文件名String word = new String(Character.toChars(unicode)); // 将unicode转换为数字boolean downloaded = false;int retryCnt = 0; // 下载失败重复次数while (!downloaded && retryCnt < RETRY_MAX) {try {String content = DownloadPage(word);SaveToFile(filePath, content);downloaded = true;threadCnt(-1);System.out.println(String.format("%s, %s, 下载成功!线程数目:%s 用时:%s",unicode, word, threadCnt(0), System.currentTimeMillis()- t1));return;} catch (Exception e) {retryCnt++;}}threadCnt(-1);System.err.println(String.format("%s, %s, 下载失败!线程数目:%s 用时:%s", unicode,word, threadCnt(0), System.currentTimeMillis() - t1));}/*** 在汉典网站上查找汉字,返回汉字字典页面内容* @param word* @return* @throws Exception*/public String DownloadPage(String word) throws Exception{//查找wordHttpclient httpclient = new Httpclient();String url = String.format(SEARCH_URL, URLEncoder.encode(word, "UTF-8"));httpclient.processUrl(url, Httpclient.METHOD_POST);//返回的是一个跳转页//获取跳转的链接Matcher mat = Pattern.compile("(?<=HREF=\")[^\"]+").matcher(httpclient.getContent());if(mat.find()){httpclient.processUrl(mat.group());}return httpclient.getContent();}/*** 将内容content写入file文件* @param file* @param content*/public void SaveToFile(String file, String content){try {FileWriter fw = new FileWriter(file);fw.write(content);fw.close();} catch (Exception e) {e.printStackTrace();}}
}
PinYin.java
package com.siqi.pinyin;import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.HashMap;
import java.util.Map;public class PinYin {private static Map<Integer, PinYinEle> map = new HashMap<Integer, PinYinEle>();/*** 载入pinyin数据文件*/static {try {BufferedReader bReader = new BufferedReader(new InputStreamReader(PinYin.class.getResourceAsStream("data.dat")));String aLine = null;while ((aLine = bReader.readLine()) != null) {PinYinEle ele = new PinYinEle(aLine);map.put(ele.getUnicode(), ele);}bReader.close();} catch (Exception e) {e.printStackTrace();}}/*** 去掉注释可以测试一下* * @param args*/public static void main(String[] args) {System.out.println(" 包含声调:" + PinYin.getPinYin("大家haome12345"));System.out.println("不包含声调:" + PinYin.getPinYin("大家haome12345", false));}/*** 获取汉字字符串的拼音,containsNumber是否获取拼音中的声调1、2、3、4* * @param str* @param containsNumber* true = 包含声调,false = 不包含声调* @return*/public static String getPinYin(String str, boolean containsNumber) {StringBuffer sb = new StringBuffer();for (Character ch : str.toCharArray()) {sb.append(getPinYin(ch, containsNumber));}return sb.toString();}/*** 获取字符串的拼音* * @param str* @return*/public static String getPinYin(String str) {StringBuffer sb = new StringBuffer();for (Character ch : str.toCharArray()) {sb.append(getPinYin(ch));}return sb.toString();}/*** 获取单个汉字的拼音,包含声调* * @param ch* @return*/public static String getPinYin(Character ch) {return getPinYin(ch, true);}/*** 获取单个汉字的拼音* * @param ch* 汉字. 如果输入非汉字,返回ch. 如果输入null,返回空字符串;* @param containsNumber* true = 包含声调,false = 不包含声调* @return*/public static String getPinYin(Character ch, boolean containsNumber) {if (ch != null) {int code = ch.hashCode();if (map.containsKey(code)) {if (containsNumber) {return map.get(code).getPinyin();} else {return map.get(code).getPinyin().replaceAll("[0-9]", "");}} else {return ch.toString();}}return "";}
}
PinYinEle.java
package com.siqi.pinyin;public class PinYinEle {private int unicode;private String ch;private String pinyin;public PinYinEle(){}public PinYinEle(String str){if(str!=null){String[] strs = str.split(",");if(strs.length == 3){try{this.unicode = Integer.parseInt(strs[0]);}catch(Exception e){}this.ch = strs[1];this.pinyin = strs[2];}}}public int getUnicode() {return unicode;}public void setUnicode(int unicode) {this.unicode = unicode;}public String getCh() {return ch;}public void setCh(String ch) {this.ch = ch;}public String getPinyin() {return pinyin;}public void setPinyin(String pinyin) {this.pinyin = pinyin;}}
生成的data.dat里面内容(部分)为:
19968,一,yi1
19969,丁,ding1
19970,丂,kao3
19971,七,qi1
19972,丄,shang4
19973,丅,xia4
19974,丆,han3
19975,万,wan4
19976,丈,zhang4
19977,三,san1
19978,上,shang4
19979,下,xia4
19980,丌,qi2
19981,不,bu4
执行时间可能会有几十分钟到几小时不等,总共会下载200+M的网页(20000+个网页),每次运行都会先判断以前下载过没有,所以结束掉程序不会有影响
显示All prepared!表示已经准备好了,刷新项目文件夹,可以看到网页保持在dict/pages下面,不建议在elipse中打开那个文件夹,因为里面有2万多个文件,会卡死eclipse,
还可以看到生成了data.txt文件,改为data.dat并复制到pinyin文件夹下面
运行PinYin.java
可以看到"大家haome12345"的拼音:
包含声调:da4jia1haome12345
不包含声调:dajiahaome12345
上面只是显示了如何获取拼音,获取笔画等的方法类似,在这里就不演示了。
转载请注明出处