您的位置:首页 > 编程语言 > Java开发

java 汉字字典,获取汉字拼音,拼音首字母,五笔,笔画,笔画顺序

2013-02-06 19:32 1041 查看
最新的可以下载的包(原来写的丢失了,重新写了个):

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.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,简版

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.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 "";

}
}


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_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();
}
}
}


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


运行DictMain.java结果



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



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

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

运行PinYin.java

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

 包含声调:da4jia1haome12345
不包含声调:dajiahaome12345


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

转载请注明出处
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: