1
2
3
4 package com.ozacc.mail.fetch.impl.sk_jp.io;
5
6 import java.io.ByteArrayOutputStream;
7 import java.io.UnsupportedEncodingException;
8
9 /***
10 * 文字関係のコンバータです。
11 * 一部コードのオリジナルは<a href="http://www-cms.phys.s.u-tokyo.ac.jp/~naoki/CIPINTRO/CCGI/kanjicod.html">Japanese Kanji Code</a>にて公開されているものです。
12 * また、http://www.sk-jp.com/cgi-bin/treebbs.cgi?kako=1&all=644&s=681
13 * にて YOSI さんが公開されたコードも参考にしています(というか実質同じです)。
14 *
15 * @author Shin
16 * @version $Revision: 1.1.2.1 $ $Date: 2005/01/18 07:20:36 $
17 */
18 public class CharCodeConverter {
19 public static final byte[] SJIS_KANA;
20 static {
21 try {
22
23 SJIS_KANA = "。「」、・ヲァィゥェォャュョッーアイウエオカキクケコサシスセソタチツテトナニヌネノハヒフヘホマミムメモヤユヨラリルレロワン゛゜".getBytes("Shift_JIS");
24 } catch (UnsupportedEncodingException e) {
25 throw new RuntimeException("CANT HAPPEN");
26 }
27 }
28
29 /***
30 * Shift_JIS エンコーディングスキームに基づくバイト列を
31 * ISO-2022-JP エンコーディングスキームに変換します。
32 * 「半角カナ」は対応する全角文字に変換します。
33 */
34 public static byte[] sjisToJis(byte[] sjisBytes) {
35 ByteArrayOutputStream out = new ByteArrayOutputStream();
36 boolean nonAscii = false;
37 int len = sjisBytes.length;
38 for (int i = 0; i < len; i++ ) {
39 if (sjisBytes[i] >= 0) {
40 if (nonAscii) {
41 nonAscii = false;
42 out.write(0x1b);
43 out.write('(');
44 out.write('B');
45 }
46 out.write(sjisBytes[i]);
47 } else {
48 if (!nonAscii) {
49 nonAscii = true;
50 out.write(0x1b);
51 out.write('$');
52 out.write('B');
53 }
54 int b = sjisBytes[i] & 0xff;
55 if (b >= 0xa1 && b <= 0xdf) {
56
57 int kanaIndex = (b - 0xA1) * 2;
58 sjisToJis(out, SJIS_KANA[kanaIndex], SJIS_KANA[kanaIndex + 1]);
59 } else {
60 i++;
61 if (i == len) break;
62 sjisToJis(out, sjisBytes[i - 1], sjisBytes[i]);
63 }
64 }
65 }
66 if (nonAscii) {
67 out.write(0x1b);
68 out.write('(');
69 out.write('B');
70 }
71 return out.toByteArray();
72 }
73 /***
74 * 1文字の2バイト Shift_JIS コードを JIS コードに変換して書き出します。
75 */
76 private static void sjisToJis(
77 ByteArrayOutputStream out, byte bh, byte bl) {
78 int h = (bh << 1) & 0xFF;
79 int l = bl & 0xFF;
80 if (l < 0x9F) {
81 if (h < 0x3F) h += 0x1F; else h -= 0x61;
82 if (l > 0x7E) l -= 0x20; else l -= 0x1F;
83 } else {
84 if (h < 0x3F) h += 0x20; else h -= 0x60;
85 l -= 0x7E;
86 }
87 out.write(h);
88 out.write(l);
89 }
90
91 /***
92 * 配列はワイドキャラクタの境界にないことを前提としています。
93 * また、エスケープシーケンスが適切に含まれることも前提です。
94 * エスケープシーケンスが"(B"/"$B"以外の場合は無視します。
95 */
96 public byte[] jisTosjis(byte[] jisBytes) {
97 ByteArrayOutputStream out = new ByteArrayOutputStream();
98 boolean nonAscii = false;
99 boolean kana = false;
100 int len = jisBytes.length;
101 for (int i = 0; i < len; i++) {
102 if (jisBytes[i] == 0x1b) {
103 if (i + 2 >= len) break;
104 if (jisBytes[i + 1] == '$' && jisBytes[i + 2] == 'B') {
105 nonAscii = true;
106 i += 2;
107 } else if (jisBytes[i + 1] == '(' && jisBytes[i + 2] == 'I') {
108 kana = true;
109 i += 2;
110 } else if (jisBytes[i + 1] == '(' && jisBytes[i + 2] == 'B') {
111 nonAscii = false;
112 kana = false;
113 i += 2;
114 } else {
115
116 nonAscii = false;
117 kana = false;
118 }
119 continue;
120 }
121 if (jisBytes[i] == 0x0e) {
122 kana = true;
123 continue;
124 }
125 if (jisBytes[i] == 0x0f) {
126 kana = false;
127 continue;
128 }
129 if (kana) {
130 out.write(jisBytes[i] | 0x80);
131 } else if (nonAscii) {
132 i++;
133 if (i == jisBytes.length) break;
134 jisToSjis(out, jisBytes[i - 1], jisBytes[i]);
135 } else {
136 out.write(jisBytes[i]);
137 }
138 }
139 return out.toByteArray();
140 }
141 /***
142 * 1文字の2バイト JIS コードを Shift_JIS に変換して書き出します。
143 */
144 private static void jisToSjis(
145 ByteArrayOutputStream out, byte bh, byte bl) {
146 int h = bh & 0xFF;
147 int l = bl & 0xFF;
148 if ((h & 0x01) > 0) {
149 h >>= 1;
150 if (h < 0x2F) h += 0x71; else h -= 0x4F;
151 if (l > 0x5F) l += 0x20; else l += 0x1F;
152 } else {
153 h >>= 1;
154 if (h < 0x2F) h += 0x70; else h -= 0x50;
155 l += 0x7E;
156 }
157 out.write(h);
158 out.write(l);
159 }
160 }