Java 文字を JIS X 0208 "x-JIS0208" エンコーディング (または、Shift-JIS ではなく EUC-JP などの互換性のあるエンコーディング) に変換しようとしていますが、統合 (マージ) コードポイントを正しく処理したいと考えています。
たとえば、この JISX0208 チャートでは、25 行 66 列に「高」が割り当てられており、類似文字の「髙」は、割り当てられていないコードポイントに分類されますが、前者とマージされます。ウィキペディアから引用します。「フォーム [ ] (高) と、はしごのような構造を持つあまり一般的でないフォーム (髙) の両方が、同じコード ポイントに組み込まれています」。
以下のコードでこれを試してみましたが、どのエンコーディングを試しても、常に例外または割り当てられていない文字プレースホルダー?
(ASCII または全角) が発生します。
おそらく異なるエンドディングまたはまったく異なる変換方法があるので、これらの文字は両方とも同じコードポイントを返しますか? または、そのような文字を検索して変換する前にマージできる API はありますか?
static Charset charset1 = Charset.forName("x-JIS0208");
static Charset charset2 = Charset.forName("EUC-JP");
static Charset[] charsets = {charset1, charset2};
static CharBuffer in = CharBuffer.allocate(1);
public static void main(String[] args) throws Exception
{
CharsetEncoder[] encoders = new CharsetEncoder[charsets.length];
for (int i = 0; i < charsets.length; i++)
encoders[i] = charsets[i].newEncoder();
char[] testChars = {' ', 'A', '?', '亜', '唖', '蔭', '高', '髙'};
for (char ch : testChars)
{
System.out.print("'" + ch + "'\t(" + Integer.toHexString(ch) + ")\t=");
for (int i = 0; i < charsets.length; i++)
{
System.out.print("\t" + interpret(encode1(encoders[i], ch)));
System.out.print("\t" + interpret(encode2(charsets[i], ch)));
}
System.out.println();
}
}
private static String interpret(int i)
{
if (i == -1)
return "excepti";
if (i < 0x80)
return "'" + (char)i + "'";
return Integer.toHexString(i);
}
private static int encode1(CharsetEncoder encoder, char ch)
{
in.rewind();
in.put(ch);
in.rewind();
try
{
ByteBuffer out = encoder.encode(in);
if (out.limit() == 1)
return out.get(0) & 0xFF;
return out.get(1) & 0xFF | (out.get(0) & 0xFF) << 8;
}
catch (CharacterCodingException e)
{
return -1;
}
}
private static int encode2(Charset charset, char ch)
{
in.rewind();
in.put(ch);
in.rewind();
ByteBuffer out = charset.encode(in);
if (out.limit() == 1)
return out.get(0) & 0xFF;
return out.get(1) & 0xFF | (out.get(0) & 0xFF) << 8;
}
出力:
' ' (3000) = 2121 2121 a1a1 a1a1
'A' (ff21) = 2341 2341 a3c1 a3c1
'?' (ff1f) = 2129 2129 a1a9 a1a9
'亜' (4e9c) = 3021 3021 b0a1 b0a1
'唖' (5516) = 3022 3022 b0a2 b0a2
'蔭' (852d) = 307e 307e b0fe b0fe
'高' (9ad8) = 3962 3962 b9e2 b9e2
'髙' (9ad9) = excepti 2129 excepti '?'
注:文字列やストリームではなく、単一の文字を変換することにのみ関心があるため、実際には、変換ごとに ByteBuffer を割り当てない別の方法(存在する場合)を好みます。