最新的可以下载的包(原来写的丢失了,重新写了个):
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
项目结构:
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
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; } }
如何使用字典
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(); } } }
====打字信息开始==== 成功载入字典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; } }
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.dat StringBuffer 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.dat try { 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 ""; } }
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_MAX while(threadCnt(0)>THREAD_MAX){ try { Thread.sleep(500); } catch (InterruptedException e) { } } threadCnt(1); //线程数量+1 this.unicode = unicode; } @Override public 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{ //查找word Httpclient 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(); } } }
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; } }
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
上面只是显示了如何获取拼音,获取笔画等的方法类似,在这里就不演示了。
转载请注明出处