最近のトラックバック

2013年12月
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30 31        
無料ブログはココログ

« 2012年12月 | トップページ

2013年5月

文字コード自動判別

Javaで文字コードを判別するにはいくつかの方法がありますが、CharsetDecoderを使用する方法を以下に示します。ただし、下記のコードには以下の問題点があります。

  1. 先頭の1024バイトしかみません
  2. JISコード(ISO-2022-JP)は判別できません
  3. 自動判別すべてにいえることですが、マルチバイト文字が少ないと誤認識する可能性があります

/*
 * This code is under public domain.
 */
public class EncodingDetector {

	private static final int SIZE = 1024;

	private static final String[] CODES = new String[] {
		"UTF-8", "Windows-31J", "EUC-JP", "UTF-16BE", "UTF-16LE"
	};

	public Charset detect(InputStream ins) throws IOException {
		byte[] a = new byte[SIZE];
		CharsetDecoder cd;
		CoderResult cr;
		ByteBuffer bb;
		CharBuffer cb;
		Charset ch;
		int l;

		cb  = CharBuffer.allocate(SIZE);
		l   = ins.read(a);
		for(String s : CODES) {
			ch = Charset.forName(s);
			cd = ch.newDecoder();
			cd.onMalformedInput(CodingErrorAction.REPORT);
			bb = ByteBuffer.wrap(a, 0, l);
			cr = cd.decode(bb, cb, false);
			if(!cr.isError()) {
				return ch;
			}
		}
		return Charset.defaultCharset();
	}

}

バイト列から文字へのエンコード

バイト列から文字へのエンコードはInputStreamReaderなどでできますが、直接エンコードしたいときもあります。そのときはCharsetDecoderを使用します。

例を以下に示します。

/*
 * This code is under public domain.
 */
public class DecodeTest {

	public static int getchar(InputStream ins,
			Charset encoding) throws IOException {
		CharsetDecoder cd = encoding.newDecoder();
		ByteBuffer bb = ByteBuffer.allocate(8);
		CharBuffer cb = CharBuffer.allocate(8);
		byte[] a = new byte[8];
		int b;

		for(int i = 0; i < a.length; i++) {
			if((b = ins.read()) < 0) {
				return -1;
			}
			a[i] = (byte)b;
			bb.put(a, 0, i + 1).flip();
			if(cd.decode(bb, cb, true).isUnderflow()) {
				cd.flush(cb);
				if(cb.flip().hasRemaining()) {
					return cb.get();
				}
			} else {
				bb.clear();
			}
		}
		return -1;
	}

}

« 2012年12月 | トップページ