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 * 026 * @version 4.0 027 * @author Kazuhiko Hasegawa 028 * @since JDK5.0, 029 */ 030final class CharCodeConverter { 031 private static final byte[] SJIS_KANA; // 5.1.9.0 (2010/09/01) public ⇒ private へ変更 032 033 /** 034 * インスタンスの生成を抑止します。 035 */ 036 private CharCodeConverter() { 037 // 何もありません。(PMD エラー回避) 038 } 039 040 static { 041 try { 042 // 全角への変換テーブル 043 SJIS_KANA = "。「」、・ヲァィゥェォャュョッーアイウエオカキクケコサシスセソタチツテトナニヌネノハヒフヘホマミムメモヤユヨラリルレロワン゛゜".getBytes("Shift_JIS"); 044 } catch( final UnsupportedEncodingException ex ) { 045 throw new OgRuntimeException( "CANT HAPPEN",ex ); 046 } 047 } 048 049 /** 050 * Shift_JIS エンコーディングスキームに基づくバイト列を 051 * ISO-2022-JP エンコーディングスキームに変換します。 052 * 「半角カナ」は対応する全角文字に変換します。 053 * 054 * @param sjisBytes エンコードするShift_JISバイト配列 055 * 056 * @return 変換後のISO-2022-JP(JIS)バイト配列(not null) 057 * @og.rtnNotNull 058 */ 059 public static byte[] sjisToJis( final byte[] sjisBytes ) { 060 final ByteArrayOutputStream out = new ByteArrayOutputStream(); 061 boolean nonAscii = false; 062 final int len = sjisBytes.length; 063 for( int i=0; i<len; i++ ) { 064 if( sjisBytes[i] >= 0 ) { 065 if( nonAscii ) { 066 nonAscii = false; 067 out.write(0x1b); 068 out.write('('); 069 out.write('B'); 070 } 071 out.write(sjisBytes[i]); 072 } else { 073 if( !nonAscii ) { 074 nonAscii = true; 075 out.write(0x1b); 076 out.write('$'); 077 out.write('B'); 078 } 079 final int bt = sjisBytes[i] & 0xff; 080 if( bt>=0xa1 && bt<=0xdf ) { 081 // 半角カナは全角に変換 082 final int kanaIndex = (bt - 0xA1) * 2; 083 sjisToJis( out, SJIS_KANA[kanaIndex], SJIS_KANA[kanaIndex+1] ); 084 } else { 085 i++; 086 if( i==len ) { break; } 087 sjisToJis( out, sjisBytes[i-1], sjisBytes[i] ); 088 } 089 } 090 } 091 if( nonAscii ) { 092 out.write(0x1b); 093 out.write('('); 094 out.write('B'); 095 } 096 return out.toByteArray(); 097 } 098 099 /** 100 * 1文字の2バイト Shift_JIS コードを JIS コードに変換して書き出します。 101 * 102 * @param outStrm 出力するByteArrayOutputStream 103 * @param bhi 変換する上位バイト 104 * @param blo 変換する下位バイト 105 */ 106 private static void sjisToJis( final ByteArrayOutputStream outStrm, final byte bhi, final byte blo ) { 107 int hi = (bhi << 1) & 0xFF; 108 int lo = blo & 0xFF; 109 if( lo < 0x9F ) { 110 if( hi<0x3F) { hi += 0x1F; } else { hi -= 0x61; } 111 if( lo>0x7E) { lo -= 0x20; } else { lo -= 0x1F; } 112 } else { 113 if( hi<0x3F) { hi += 0x20; } else { hi -= 0x60; } 114 lo -= 0x7E; 115 } 116 outStrm.write(hi); 117 outStrm.write(lo); 118 } 119}