第044回_EncodingDecl4
»
前回の続きで実装の紹介(後半)をします。
文字符号化方式の自動検知機能の実装2:文字符号化方式ファミリ毎の実装
文字符号化方式ファミリの実装は次のようにします。
■基底クラスの実装
■UTF-8 BOM付
■UTF-8 BOM無
■UTF-16BE
■UTF-16LE
■Unknown
■基底クラスの実装
public abstract class AbstractEncodingFamily
{
private FileInputStream m_input;
private byte[] m_startByte;
private byte[][] m_literalByte;
private byte[] m_endByte;
private byte[][] m_supportedEncodingName_ByteOrders;
private AbstractEncoding[] m_supportedEncoding;
private AbstractEncoding m_defaultEncoding;
private AbstractEncoding m_errorEncoding;
private byte[][] m_sddeclLiteral;
private int m_wordSize;
public AbstractEncodingFamily(
byte[] startByte,
byte[][] literalByte,
byte[] endByte,
byte[][] supportedEncodingName_ByteOrders,
AbstractEncoding[] supportedEncoding,
AbstractEncoding defaultEncoding,
byte[][] sddeclLiteral
)
{
m_input = null;
m_startByte = startByte;
m_literalByte = literalByte;
m_endByte = endByte;
m_supportedEncodingName_ByteOrders
= supportedEncodingName_ByteOrders;
m_supportedEncoding = supportedEncoding;
m_defaultEncoding = defaultEncoding;
ErrorEncoding tmp = new ErrorEncoding();
tmp.setUnSpportedEncName();
m_errorEncoding = tmp;
m_sddeclLiteral = sddeclLiteral;
m_wordSize = (endByte==null) ? 0 : endByte.length;
}
public AbstractEncoding getDefaultEncoding()
{
return m_defaultEncoding;
}
public byte[] getLiteral(FileInputStream input)
{
m_input = input;
byte[] retval = null;
//>か先頭"か先頭'を探索する
byte[] byteOrder = this.searchLiteralStartByte();
//最後まで読み込んでしまった
if (byteOrder == null)
{
//retval = null;
}
//最後まで読み込む前にキーワードを見つけた
else
{
//読み込み条件の最後(>)か確認する
boolean end = this.compareByteOrder(m_endByte, byteOrder);
//読み込み条件の最後の場合
if(end)
{
//retval = null;
}
//リテラルの開始を見つけた場合
else
{
//末尾を探索して末尾までのリテラルの内容を取得する
retval = this.getLiteralUntilEndByte(byteOrder);
}
}
return retval;
}
//>か先頭"か先頭'を探索する]
//
// 戻り値: null 最後まで読み込んだ
// null以外 リテラルのスタートか読み込み条件の
// 最後(>)を見つけた
private byte[] searchLiteralStartByte()
{
byte[] retval = null;
byte[] buf = new byte[m_wordSize];
int len = 0;
try
{
label0:
while(true)
{
//指定byte読み取る
len = m_input.read(buf);
//読み込めなかった場合
if (len == -1)
{
//終了
retval = null;
break;
}
//読み込めた場合
else
{
boolean b1 = this.matchOfLiteralByte(buf);
boolean b2 = this.compareByteOrder(m_endByte, buf);
if (b1 || b2)
{
retval = buf;
break label0;
}
else
{
//何もしない
}
}
}
}
catch (IOException e)
{
// TODO 自動生成された catch ブロック
e.printStackTrace();
}
return retval;
}
private boolean matchOfLiteralByte(byte[] buf)
{
boolean retval = false;
for(byte[] literalByte : m_literalByte)
{
//比較する
boolean b = compareByteOrder(literalByte, buf);
retval = retval || b;
//見つかったところでbreakしても良い
}
return retval;
}
private byte[] getLiteralUntilEndByte(byte[] endByteOfLiteral)
{
ArrayList<Byte> blist = new ArrayList<Byte>();
boolean errorFlag=false;
byte[] buf = new byte[m_wordSize];
int len = 0;
try
{
while(true)
{
//1byte読み取る
len = m_input.read(buf);
//読み込めなかった場合
if (len == -1)
{
errorFlag = true;
//終了
break;
}
//読み込めた場合
else
{
//末尾かどうか判定する
boolean b
= this.compareByteOrder(endByteOfLiteral, buf);
//末尾に到達した場合
if (b)
{
//終了
break;
}
//末尾に到達していない場合
else
{
for(byte byteOrder: buf)
{
Byte tmp = new Byte(byteOrder);
blist.add(tmp);
}
}
}
}
}
catch (IOException e)
{
// TODO 自動生成された catch ブロック
e.printStackTrace();
errorFlag = true;
}
//戻り値を宣言する
byte[] retval = null;
//エラーフラグがある場合
if(errorFlag)
{
//何もしない
//retval = null;
}
//エラーフラグがない場合
else
{
//サイズを計算する
int size = blist.size();
retval = new byte[size];
for(int i=0; i<size;i++)
{
retval[i]= blist.get(i);
}
}
return retval;
}
//サポートする文字符号化方式を取得する
public AbstractEncoding getEncoding(byte[] literal)
{
AbstractEncoding retval = m_errorEncoding;
//SDDeclのリテラルか判定する
boolean b = this.isSDDeclLiteral(literal);
//SDDeclのリテラルの場合
if (b)
{
//エンコーディング宣言未指定なのでデフォルトを設定する
retval = this.getDefaultEncoding();
}
//SDDeclのリテラルでない場合(エンコーディング宣言のリテラルの場合)
else
{
//サポートする文字符号化方式のEncNameのバイト列と比較する
int len = m_supportedEncodingName_ByteOrders.length;
for (int i=0; i<len; i++)
{
byte[] byteOrder = m_supportedEncodingName_ByteOrders[i];
boolean b2 = compareByteOrder(byteOrder, literal);
//一致する場合
if (b2)
{
retval = m_supportedEncoding[i];
}
//一致しない場合
else
{
//次へ
}
}
}
return retval;
}
private boolean isSDDeclLiteral(byte[] literal)
{
boolean retval = false;
for(byte[] base : m_sddeclLiteral)
{
boolean b = compareByteOrder(base, literal);
retval = retval || b;
}
return retval;
}
public boolean startMatch(byte[] buf)
{
boolean retval = true;
//基準とbufを比較する
retval = this.compareByteOrder(m_startByte, buf);
return retval;
}
//バイトの並びを比較する
// base 比較元(基準)
// literal 比較対象
//
// 基準のbyteOrderよりliteralのバイト長が小さい場合はfalseを返す
//
protected boolean compareByteOrder(byte[] base, byte[] literal)
{
boolean retval = true;
int baseLen = base.length;
int literalLen = literal.length;
//リテラルのバイト数が基準より少ない場合
if (baseLen > literalLen)
{
retval = false;
}
//リテラルのバイト数が基準以上の場合
else
{
for(int i=0; i<baseLen; i++)
{
//i番目の文字が一致する場合
if(base[i]==literal[i])
{
//次へ
continue;
}
//i番目の文字が一致しない場合
else
{
retval = false;
//比較終了
break;
}
}
}
return retval;
}
//Unknownだけfalseを返すためデフォルトはtrueを返す
public boolean needLiteralSeaching()
{
return true;
}
}
public class Utf_8WithBomFamily extends AbstractEncodingFamily
{
// BOM Sequence
private static final byte m_startByte[]
={(byte)0xEF,(byte)0xBB,(byte)0xBF};
private static final byte[][] m_literalByte ={
{0x22}, // "
{0x27}, // '
};
// <
private static final byte[] m_endByte = {0x3E};
private static final byte[][] m_supportedEncodingName_ByteOrders =
{
//U T F - 8
{0x55, 0x54, 0x46, 0x2D, 0x38},
};
private static final AbstractEncoding[] m_supportedEncoding =
{
new Utf_8WithBomEncoding(),
};
//もしエンコーディング宣言がなかった場合の符号化文字方式
private static final AbstractEncoding m_encoding
= new Utf_8WithBomEncoding();
private static final byte[][] m_sddeclLiteral =
{
//y e s
{0x79, 0x65, 0x73},
//n o
{0x6E, 0x6F},
};
public Utf_8WithBomFamily()
{
super(m_startByte, m_literalByte, m_endByte,
m_supportedEncodingName_ByteOrders,
m_supportedEncoding, m_encoding, m_sddeclLiteral);
}
}
public class Utf_8WithoutBomFamily extends AbstractEncodingFamily
{
// < ? x m
private static final byte m_startByte[]={0x3C,0x3F,0x78,0x6D};
private static final byte[][] m_literalByte ={
{0x22}, // "
{0x27}, // '
};
// <
private static final byte[] m_endByte = {0x3E};
private static final byte[][] m_supportedEncodingName_ByteOrders =
{
//U T F - 8
{0x55, 0x54, 0x46, 0x2D, 0x38},
};
private static final AbstractEncoding[] m_supportedEncodingName =
{
new Utf_8WithoutBomEncoding(),
};
//もしエンコーディング宣言がなかった場合の符号化文字方式
private static final AbstractEncoding m_encoding
=new Utf_8WithoutBomEncoding();
private static final byte[][] m_sddeclLiteral =
{
//y e s
{0x79, 0x65, 0x73},
//n o
{0x6E, 0x6F},
};
public Utf_8WithoutBomFamily()
{
super(m_startByte, m_literalByte, m_endByte,
m_supportedEncodingName_ByteOrders,
m_supportedEncodingName, m_encoding, m_sddeclLiteral);
}
}
public class Utf_16BEWithBomFamily extends AbstractEncodingFamily
{
// BOM Sequence
private static final byte m_startByte[]={(byte) 0xFE,(byte) 0xFF};
private static final byte[][] m_literalByte ={
{0x00, 0x22},
{0x00, 0x27},
};
private static final byte[] m_endByte = {0x00, 0x3E};
private static final byte[][] m_supportedEncodingName_ByteOrders =
{
// U T F -
{0x00, 0x55, 0x00, 0x54, 0x00, 0x46, 0x00, 0x2D,
// 1 6
0x00, 0x31, 0x00, 0x36},
};
private static final AbstractEncoding[] m_supportedEncodingName =
{
new Utf_16Encoding(),
};
//もしエンコーディング宣言がなかった場合の符号化文字方式
private static final AbstractEncoding m_encoding
=new Utf_16Encoding();
private static final byte[][] m_sddeclLiteral =
{
// y e s
{0x00, 0x79, 0x00, 0x65, 0x00, 0x73},
// n o
{0x00, 0x6E, 0x00, 0x6F},
};
public Utf_16BEWithBomFamily()
{
super(m_startByte, m_literalByte, m_endByte,
m_supportedEncodingName_ByteOrders,
m_supportedEncodingName, m_encoding, m_sddeclLiteral);
}
}
public class Utf_16LEWithBomFamily extends AbstractEncodingFamily
{
// BOM Sequence
private static final byte m_startByte[]={(byte) 0xFF,(byte) 0xFE};
private static final byte[][] m_literalByte ={
{0x22, 0x00}, // "
{0x27, 0x00}, // '
};
// <
private static final byte[] m_endByte = {0x3E, 0x00};
private static final byte[][] m_supportedEncodingName_ByteOrders =
{
//U T F -
{0x55, 0x00, 0x54, 0x00, 0x46, 0x00, 0x2D, 0x00,
//1 6
0x31, 0x00, 0x36, 0x00},
};
private static final AbstractEncoding[] m_supportedEncodingName =
{
new Utf_16Encoding(),
};
private static final byte[][] m_sddeclLiteral =
{
//y e s
{0x79, 0x00, 0x65, 0x00, 0x73, 0x00},
//n o
{0x6E, 0x00, 0x6F, 0x00},
};
//もしエンコーディング宣言がなかった場合の符号化文字方式
private static final AbstractEncoding m_encoding=new Utf_16Encoding();
public Utf_16LEWithBomFamily()
{
super(m_startByte, m_literalByte, m_endByte,
m_supportedEncodingName_ByteOrders,
m_supportedEncodingName, m_encoding, m_sddeclLiteral);
}
}
public class UnknownEncodingFamily extends AbstractEncodingFamily
{
//デフォルトエンコーディング
private static final AbstractEncoding m_encoding
=new Utf_8WithoutBomEncoding();
public UnknownEncodingFamily()
{
super(null, null, null, null,null, m_encoding, null);
}
public boolean needLiteralSeaching()
{
return false;
}
}
文字符号化方式の自動検知機能の実装2:文字符号化方式ファミリ毎の実装
文字符号化方式の実装は次のようにします。
■基底クラス
■UTF-8BOM付
■UTF-8BOM無
■UTF-16
■Error
■基底クラス
public abstract class AbstractEncoding
{
public boolean isError()
{
return false;
}
public abstract BufferedReader getBR(String path);
protected BufferedReader getBR(String path, String encoding)
{
BufferedReader br = null;
//FileReaderを作成し、1行トークナイザに設定する
try
{
File file = new File(path);
@SuppressWarnings("resource")
FileInputStream fis = new FileInputStream(file);
InputStreamReader reader = new InputStreamReader(fis, encoding);
br = new BufferedReader(reader);
}
catch (FileNotFoundException e)
{
// TODO 自動生成された catch ブロック
e.printStackTrace();
}
catch (UnsupportedEncodingException e)
{
// TODO 自動生成された catch ブロック
e.printStackTrace();
}
return br;
}
}
public class Utf_8WithBomEncoding extends AbstractEncoding
{
private static final String m_encoding = "UTF-8";
public BufferedReader getBR(String path)
{
BufferedReader br = null;
//FileReaderを作成し、1行トークナイザに設定する
try
{
File file = new File(path);
FileInputStream fis = new FileInputStream(file);
//BOMは自動で無視できないのでスキップする
this.skipBOM(fis);
InputStreamReader reader
= new InputStreamReader(fis, m_encoding);
br = new BufferedReader(reader);
}
catch (FileNotFoundException e)
{
// TODO 自動生成された catch ブロック
e.printStackTrace();
}
catch (UnsupportedEncodingException e)
{
// TODO 自動生成された catch ブロック
e.printStackTrace();
}
return br;
}
private void skipBOM(FileInputStream fis)
{
//BOMは3バイト
byte[] b= new byte[3];
try
{
//3バイト読み込み、捨てる
fis.read(b);
}
catch (IOException e)
{
// TODO 自動生成された catch ブロック
e.printStackTrace();
}
}
}
public class Utf_8WithoutBomEncoding extends AbstractEncoding
{
private static final String m_encoding = "UTF-8";
public BufferedReader getBR(String path)
{
return getBR(path, m_encoding);
}
}
public class Utf_16Encoding extends AbstractEncoding
{
private static final String m_encoding = "UTF-16";
@Override
public BufferedReader getBR(String path)
{
return getBR(path, m_encoding);
}
}
public class ErrorEncoding extends AbstractEncoding
{
private enum Error_Value
{
NOT_ERROR, //0 初期値
FILE_NOT_FOUND, //1 ファイルがオープンできなかった
NO_VERSION_NUM, //3 version_numのリテラルが見つけられなかった
UNSUPPORTED_ENC_NAME //4 対応していないEncName
};
private Error_Value m_errorValue;
public ErrorEncoding()
{
m_errorValue = Error_Value.NOT_ERROR;
}
@Override
public boolean isError()
{
return true;
}
@Override
public BufferedReader getBR(String path)
{
return null;
}
public void setFileNotException()
{
m_errorValue = Error_Value.FILE_NOT_FOUND;
}
public void setNoVersionNumLiteral()
{
m_errorValue = Error_Value.NO_VERSION_NUM;
}
public void setUnSpportedEncName()
{
m_errorValue = Error_Value.UNSUPPORTED_ENC_NAME;
}
}
コメント
コメントを投稿する
SpecialPR