最近のトラックバック

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        
無料ブログはココログ

Java

文字コード自動判別

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;
	}

}

10進浮動小数点(Decimal64, 32)クラスを作成しました

10進浮動小数点(Decimal64, Decimal32)を扱うクラスを作成しました。

通常の2進浮動小数点(double等)では10進数を正確に表せなくなる可能性がありますが、
10進浮動小数点では10進数でデータを持つのでこの可能性はなくなります。
(しかし、1/3*3=1とはなりません)

また、この副産物としてBCD(2進化10進数)を扱うクラスを作成しました。
RDBのNUMERIC型をそのまま保存できるので、DBとのインターフェースに使用できると思います。

JSONパーサを作成しました

JSON形式の文字列・ファイルを読み込みJavaのListとMapに変換するパーサを作成しました。
Schluesselにも反映させる予定です。

開平法

筆算における開平法をJavaで実現したソースを以下に示します。
正確な整数の平方根を求めるときに使用できると思います。

参考:
Wikipedia: http://ja.wikipedia.org/wiki/%E9%96%8B%E5%B9%B3%E6%B3%95
ニコニコ大百科: http://dic.nicovideo.jp/a/%E9%96%8B%E5%B9%B3%E6%B3%95

// ------------------------------------------
// This code is public domain.
public class ExactSqrt {

private static int toInt(byte b) {
return (b < 0) ? (b & 0x7f) + 128 : b;
}

private static final int BASE = 16;

public static void main(String[] args) {
byte[] a;
long q = 123454321;
int i = 0;
int s = 0;
int t = 0;
int r = 0;

a = BigInteger.valueOf(q).toByteArray();
while(a[i] == 0);
for(; i < a.length; i++) {
int x = 0;

if(s == 0) {
t = toInt(a[i]);
x = s = (int)Math.sqrt(t);
} else {
int s0 = s;

t = (t * BASE * BASE) + toInt(a[i]);
do {
s = (s0 * BASE) + x;
} while(x++ * s <= t);
x -= 2;
s = (s0 * BASE) + x;
}
t = t - x * s;
s = s + x;
r = (r * BASE) + x;
}

if(t == 0) {
System.out.println("Exact: " + r);
} else {
System.out.println("Inexact: " + r);
}
}

}
// code end
// ------------------------------------------

正規表現エンジン作成ほぼ完了

正規表現エンジン(NFAからDFAの変換・DFAエンジン)の作成がほぼ完了しました。
これからSchemeへの結合をしたいと思います。

正規表現エンジン作成中

「#構文」をSchemeで定義できるようにすることと、将来的にはリーダのソースのリファクタリングを目標として簡単な正規表現エンジンを作成しています。
(Javaの正規表現エンジンではlexのようなパターンマッチはできないため)

NFA正規表現エンジンがある程度動くようになりました。
このエンジンはJavaのライブラリとしても使用できるようにする予定です。

正規表現エンジン・LALR(1)構文解析エンジンの実装

Schluesselにリードマクロ的な文法の拡張機能を追加すると同時にリーダのリファクタリングをしたいと思っています。
そのため、Schemeとは関係ありませんが、過去に作成してあった正規表現エンジンとLALR(1)構文解析エンジンを改変してSchluesselに組み込む作業をしていました。
コーディングの作業はある程度完了しました。これから動作確認したいと思います。

その他のカテゴリー