001/* 002 * Copyright (c) 2009 The openGion Project. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, 013 * either express or implied. See the License for the specific language 014 * governing permissions and limitations under the License. 015 */ 016package org.opengion.fukurou.mail; 017 018import java.io.ByteArrayOutputStream; 019import java.io.UnsupportedEncodingException; 020 021import org.opengion.fukurou.system.OgRuntimeException ; // 6.4.2.0 (2016/01/29) 022 023/** 024 * 文字関係のコンバータです。 025 * 一部コードのオリジナルは <a href="http://www-cms.phys.s.u-tokyo.ac.jp/~naoki/CIPINTRO/CCGI/kanjicod.html">Japanese Kanji Code</a>にて公開されているものです。 026 * また、http://www.sk-jp.com/cgi-bin/treebbs.cgi?kako=1&all=644&s=681 027 * にて YOSI さんが公開されたコードも参考にしています(というか実質同じです)。 028 * 029 * @version 4.0 030 * @author Kazuhiko Hasegawa 031 * @since JDK5.0, 032 */ 033final class CharCodeConverter { 034 private static final byte[] SJIS_KANA; // 5.1.9.0 (2010/09/01) public ⇒ private へ変更 035 036 /** 037 * インスタンスの生成を抑止します。 038 */ 039 private CharCodeConverter() { 040 // 何もありません。(PMD エラー回避) 041 } 042 043 static { 044 try { 045 // 全角への変換テーブル 046 SJIS_KANA = "。「」、・ヲァィゥェォャュョッーアイウエオカキクケコサシスセソタチツテトナニヌネノハヒフヘホマミムメモヤユヨラリルレロワン゛゜".getBytes("Shift_JIS"); 047 } catch( final UnsupportedEncodingException ex ) { 048 throw new OgRuntimeException( "CANT HAPPEN",ex ); 049 } 050 } 051 052 /** 053 * Shift_JIS エンコーディングスキームに基づくバイト列を 054 * ISO-2022-JP エンコーディングスキームに変換します。 055 * 「半角カナ」は対応する全角文字に変換します。 056 * 057 * @param sjisBytes エンコードするShift_JISバイト配列 058 * 059 * @return 変換後のISO-2022-JP(JIS)バイト配列(not null) 060 * @og.rtnNotNull 061 */ 062 public static byte[] sjisToJis( final byte[] sjisBytes ) { 063 final ByteArrayOutputStream out = new ByteArrayOutputStream(); 064 boolean nonAscii = false; 065 final int len = sjisBytes.length; 066 for( int i=0; i<len; i++ ) { 067 if( sjisBytes[i] >= 0 ) { 068 if( nonAscii ) { 069 nonAscii = false; 070 out.write(0x1b); 071 out.write('('); 072 out.write('B'); 073 } 074 out.write(sjisBytes[i]); 075 } else { 076 if( !nonAscii ) { 077 nonAscii = true; 078 out.write(0x1b); 079 out.write('$'); 080 out.write('B'); 081 } 082 final int bt = sjisBytes[i] & 0xff; 083 if( bt>=0xa1 && bt<=0xdf ) { 084 // 半角カナは全角に変換 085 final int kanaIndex = (bt - 0xA1) * 2; 086 sjisToJis( out, SJIS_KANA[kanaIndex], SJIS_KANA[kanaIndex+1] ); 087 } else { 088 i++; 089 if( i==len ) { break; } 090 sjisToJis( out, sjisBytes[i-1], sjisBytes[i] ); 091 } 092 } 093 } 094 if( nonAscii ) { 095 out.write(0x1b); 096 out.write('('); 097 out.write('B'); 098 } 099 return out.toByteArray(); 100 } 101 102 /** 103 * 1文字の2バイト Shift_JIS コードを JIS コードに変換して書き出します。 104 * 105 * @param outStrm 出力するByteArrayOutputStream 106 * @param bhi 変換する上位バイト 107 * @param blo 変換する下位バイト 108 */ 109 private static void sjisToJis( final ByteArrayOutputStream outStrm, final byte bhi, final byte blo ) { 110 int hi = (bhi << 1) & 0xFF; 111 int lo = blo & 0xFF; 112 if( lo < 0x9F ) { 113 if( hi<0x3F) { hi += 0x1F; } else { hi -= 0x61; } 114 if( lo>0x7E) { lo -= 0x20; } else { lo -= 0x1F; } 115 } else { 116 if( hi<0x3F) { hi += 0x20; } else { hi -= 0x60; } 117 lo -= 0x7E; 118 } 119 outStrm.write(hi); 120 outStrm.write(lo); 121 } 122}