本文提供一个java实现中文字符繁简体互换的zip包以及主要的源代码实现说明。
繁简体(GB<=>Big5)中文字符的转化实现原理很简单,就是根据两种码表的编码规则,创建两者之间的字符对应关系表,通过程序读取这个映射表来自动查出另一种编码方式下对应字符的字节编码,从而进行逐字节的内容替换。
主功能实现的GB2Big5.java源代码如下:
1. package net.java2000.tools;
2.
3. import java.io.BufferedOutputStream;
4. import java.io.FileOutputStream;
5. import java.io.IOException;
6. import java.io.InputStream;
7.
8. /**
9. * 用来处理GB2312/BIG5码字符互相转换的类.<br>
10. * 需要两个码表文件: gb-big5.table,/zeal/util/big5-gb.table.<br>
11. * 这两个码表可以根据具体情况补充映射不正确的码.
12. */
13.public class GB2Big5 {
14. private static GB2Big5 pInstance = null;
15.
16. private String s_big5TableFile = null;
17.
18. private String s_gbTableFile = null;
19.
20. private byte[] b_big5Table = null;
21.
22. private byte[] b_gbTable = null;
23.
24. /** 指定两个码表文件来进行初始化 */
25. private GB2Big5(String sgbTableFile, String sbig5TableFile) throws NullPointerException {
26. s_big5TableFile = sbig5TableFile;
27. s_gbTableFile = sgbTableFile;
28. if (null == b_gbTable) {
29. b_gbTable = getBytesFromFile(sgbTableFile);
30. }
31. if (null == b_big5Table) {
32. b_big5Table = getBytesFromFile(sbig5TableFile);
33. }
34. if (null == b_gbTable) {
35. throw new NullPointerException("No gb table can be load");
36. }
37. if (null == b_big5Table) {
38. throw new NullPointerException("No big5 table can be load");
39. }
40. }
41.
42. public static synchronized GB2Big5 getInstance() {
43. // return getInstance("d:\\gb-big5.table","d:\\big5-gb.table");
44. return getInstance("/net/java2000/tools/gb-big5.table", "/net/java2000/tools/big5-gb.table");
45. }
46.
47. public static synchronized GB2Big5 getInstance(String sgbTableFile, String sbig5TableFile) {
48. if (null == pInstance) {
49. try {
50. pInstance = new GB2Big5(sgbTableFile, sbig5TableFile);
51. } catch (Exception e) {
52. System.err.println(e.toString());
53. pInstance = null;
54. }
55. }
56. return pInstance;
57. }
58.
59. /**
60. * 把gbChar对应的big5字符替换掉,用来更新码表文件. 一般当发现字符映射不正确的时候可以通过这个方法来校正.
61. */
62. protected synchronized void resetBig5Char(String gbChar, String big5Char) throws Exception {
63. byte[] Text = new String(gbChar.getBytes(), "GBK").getBytes("GBK");
64. byte[] TextBig5 = new String(big5Char.getBytes(), "BIG5").getBytes("BIG5");
65. int max = Text.length - 1;
66. int h = 0;
67. int l = 0;
68. int p = 0;
69. int b = 256;
70. for (int i = 0; i < max; i++) {
71. h = (int) (Text[i]);
72. if (h < 0) {
73. h = b + h;
74. l = (int) (Text[i + 1]);
75. if (l < 0) {
76. l = b + (int) (Text[i + 1]);
77. }
78. if (h == 161 && l == 64) {
79. ; // do nothing
80. } else {
81. p = (h - 160) * 510 + (l - 1) * 2;
82. b_gbTable[p] = TextBig5[i];
83. b_gbTable[p + 1] = TextBig5[i + 1];
84. }
85. i++;
86. }
87. }
88. BufferedOutputStream pWriter = new BufferedOutputStream(new FileOutputStream(s_gbTableFile));
89. pWriter.write(b_gbTable, 0, b_gbTable.length);
90. pWriter.close();
91. }
92.
93. /**
94. * 把big5Char对应的gb字符替换掉,用来更新码表文件. 一般当发现字符映射不正确的时候可以通过这个方法来校正.
95. */
96. protected synchronized void resetGbChar(String big5Char, String gbChar) throws Exception {
97. byte[] TextGb = new String(gbChar.getBytes(), "GBK").getBytes("GBK");
98. byte[] Text = new String(big5Char.getBytes(), "BIG5").getBytes("BIG5");
99. int max = Text.length - 1;
100. int h = 0;
101. int l = 0;
102. int p = 0;
103. int b = 256;
104. for (int i = 0; i < max; i++) {
105. h = (int) (Text[i]);
106. if (h < 0) {
107. h = b + h;
108. l = (int) (Text[i + 1]);
109. if (l < 0) {
110. l = b + (int) (Text[i + 1]);
111. }
112. if (h == 161 && l == 64) {
113. ; // do nothing
114. } else {
115. p = (h - 160) * 510 + (l - 1) * 2;
116. b_big5Table[p] = TextGb[i];
117. b_big5Table[p + 1] = TextGb[i + 1];
118. }
119. i++;
120. }
121. }
122. BufferedOutputStream pWriter = new BufferedOutputStream(new FileOutputStream(s_big5TableFile));
123. pWriter.write(b_big5Table, 0, b_big5Table.length);
124. pWriter.close();
125. }
126.
127. /** 把gb2312编码的字符串转化成big5码的字节流 */
128. public byte[] gb2big5(String inStr) throws Exception {
129. if (null == inStr || inStr.length() <= 0) {
130. return "".getBytes();
131. // return "";
132. }
133. byte[] Text = new String(inStr.getBytes(), "GBK").getBytes("GBK");
134. int max = Text.length - 1;
135. int h = 0;
136. int l = 0;
137. int p = 0;
138. int b = 256;
139. byte[] big = new byte[2];
140. for (int i = 0; i < max; i++) {
141. h = (int) (Text[i]);
142. if (h < 0) {
143. h = b + h;
144. l = (int) (Text[i + 1]);
145. if (l < 0) {
146. l = b + (int) (Text[i + 1]);
147. }
148. if (h == 161 && l == 64) {
149. big[0] = big[1] = (byte) (161 - b);
150. } else {
151. p = (h - 160) * 510 + (l - 1) * 2;
152. try {
153. big[0] = (byte) (b_gbTable[p] - b);
154. } catch (Exception e) {
155. big[0] = 45;
156. }
157. try {
158. big[1] = (byte) (b_gbTable[p + 1] - b);
159. } catch (Exception e) {
160. big[1] = 45;
161. }
162. }
163. Text[i] = big[0];
164. Text[i + 1] = big[1];
165. i++;
166. }
167. }
168. return Text;
169. // return new String(Text);
170. }
171.
172. /** 把big5码的字符串转化成gb2312码的字符串 */
173. public String big52gb(String inStr) throws Exception {
174. if (null == inStr || inStr.length() <= 0) {
175. return "";
176. }
177. byte[] Text = new String(inStr.getBytes(), "BIG5").getBytes("BIG5");
178. int max = Text.length - 1;
179. int h = 0;
180. int l = 0;
181. int p = 0;
182. int b = 256;
183. byte[] big = new byte[2];
184. for (int i = 0; i < max; i++) {
185. h = (int) (Text[i]);
186. if (h < 0) {
187. h = b + h;
188. l = (int) (Text[i + 1]);
189. if (l < 0) {
190. l = b + (int) (Text[i + 1]);
191. }
192. if (h == 161 && l == 161) {
193. big[0] = (byte) (161 - b);
194. big[1] = (byte) (64 - b);
195. } else {
196. p = (h - 160) * 510 + (l - 1) * 2;
197. try {
198. big[0] = (byte) (b_big5Table[p] - b);
199. } catch (Exception e) {
200. big[0] = 45;
201. }
202. try {
203. big[1] = (byte) (b_big5Table[p + 1] - b);
204. } catch (Exception e) {
205. big[1] = 45;
206. }
207. }
208. Text[i] = big[0];
209. Text[i + 1] = big[1];
210. i++;
211. }
212. }
213. return new String(Text);
214. }
215.
216. /** 把文件读入字节数组,读取失败则返回null */
217. private static byte[] getBytesFromFile(String inFileName) {
218. try {
219. InputStream in = GB2Big5.class.getResourceAsStream(inFileName);
220. byte[] sContent = StreamConverter.toByteArray(in);
221. in.close();
222. return sContent;
223. /*
224. * java.io.RandomAccessFile inStream = new java.io.RandomAccessFile(inFileName,"r"); byte[] sContent = new byte[ (int)
225. * (inStream.length())]; inStream.read(sContent); inStream.close(); return sContent;
226. */
227. } catch (Exception e) {
228. e.printStackTrace();
229. return null;
230. }
231. }
232.
233. public static void main(String[] args) throws Exception {
234. if (args.length < 2) {
235. System.out.println("Usage: net.java2000.tools.GB2Big5 [-gb | -big5] inputstring");
236. System.exit(1);
237. return;
238. }
239. boolean bIsGB = true;
240. String inStr = "";
241. for (int i = 0; i < args.length; i++) {
242. if (args[i].equalsIgnoreCase("-gb")) {
243. bIsGB = true;
244. } else if (args[i].equalsIgnoreCase("-big5")) {
245. bIsGB = false;
246. } else {
247. inStr = args[i];
248. }
249. }
250. GB2Big5 pTmp = GB2Big5.getInstance();
251. String outStr = "";
252. if (bIsGB) {
253. outStr = pTmp.big52gb(inStr);
254. } else {
255. outStr = new String(pTmp.gb2big5(inStr), "BIG5");
256. }
257. System.out.println("String [" + inStr + "] converted into:\n[" + outStr + "]");
258. }
259. }
260.
261. class StreamConverter {
262. public StreamConverter() {
263. }
264.
265. public static byte[] toByteArray(InputStream input) throws IOException {
266. int status = 0;
267. int totalBytesRead = 0;
268. int blockCount = 1;
269. byte dynamicBuffer[] = new byte[5000 * blockCount];
270. byte buffer[] = new byte[5000];
271. boolean endOfStream = false;
272. do {
273. if (endOfStream)
274. break;
275. int bytesRead = 0;
276. if (input.available() != 0) {
277. status = input.read(buffer);
278. endOfStream = status == -1;
279. if (!endOfStream)
280. bytesRead = status;
281. } else {
282. status = input.read();
283. endOfStream = status == -1;
284. buffer[0] = (byte) status;
285. if (!endOfStream)
286. bytesRead = 1;
287. }
288. if (!endOfStream) {
289. if (totalBytesRead + bytesRead > 5000 * blockCount) {
290. blockCount++;
291. byte newBuffer[] = new byte[5000 * blockCount];
292. System.arraycopy(dynamicBuffer, 0, newBuffer, 0, totalBytesRead);
293. dynamicBuffer = newBuffer;
294. }
295. System.arraycopy(buffer, 0, dynamicBuffer, totalBytesRead, bytesRead);
296. totalBytesRead += bytesRead;
297. }
298. } while (true);
299. byte result[] = new byte[totalBytesRead];
300. if (totalBytesRead != 0)
301. System.arraycopy(dynamicBuffer, 0, result, 0, totalBytesRead);
302. return result;
303. }
304. }