utf-16LE でエンコードされたファイルからコンテンツを取得するファイル ウォッチャーがあります。書き込まれたデータの最初のビットには、利用可能な BOM があります。これを使用して、UTF-8 に対するエンコーディングを識別していました (受信するほとんどのファイルがエンコーディングされています)。BOM をキャッチして UTF-8 に再エンコードし、パーサーが異常を起こさないようにします。問題は、ファイルが拡大するため、データのすべてのビットに BOM が含まれているわけではないことです。
これが私の質問です - 私が持っているデータの各セットに BOM バイトを追加せずに (ソースを制御できないため)、UTF-16 \000 に固有の null バイトを探してから使用できますか? BOMの代わりに私の識別子としてそれを?これにより、今後頭痛がすることはありますか?
私のアーキテクチャには、Java で記述されたパーサーが取得したときに受信したデータを一時ファイルに記録する ruby Web アプリケーションが含まれます。
私の識別/再エンコードコードは次のようになります。
// guess encoding if utf-16 then
// convert to UTF-8 first
try {
FileInputStream fis = new FileInputStream(args[args.length-1]);
byte[] contents = new byte[fis.available()];
fis.read(contents, 0, contents.length);
if ( (contents[0] == (byte)0xFF) && (contents[1] == (byte)0xFE) ) {
String asString = new String(contents, "UTF-16");
byte[] newBytes = asString.getBytes("UTF8");
FileOutputStream fos = new FileOutputStream(args[args.length-1]);
fos.write(newBytes);
fos.close();
}
fis.close();
} catch(Exception e) {
e.printStackTrace();
}
アップデート
ユーロ、em ダッシュ、およびその他の文字などをサポートしたいと考えています。上記のコードを次のように変更したところ、これらの文字のすべてのテストに合格したようです。
// guess encoding if utf-16 then
// convert to UTF-8 first
try {
FileInputStream fis = new FileInputStream(args[args.length-1]);
byte[] contents = new byte[fis.available()];
fis.read(contents, 0, contents.length);
byte[] real = null;
int found = 0;
// if found a BOM then skip out of here... we just need to convert it
if ( (contents[0] == (byte)0xFF) && (contents[1] == (byte)0xFE) ) {
found = 3;
real = contents;
// no BOM detected but still could be UTF-16
} else {
for(int cnt=0; cnt<10; cnt++) {
if(contents[cnt] == (byte)0x00) { found++; };
real = new byte[contents.length+2];
real[0] = (byte)0xFF;
real[1] = (byte)0xFE;
// tack on BOM and copy over new array
for(int ib=2; ib < real.length; ib++) {
real[ib] = contents[ib-2];
}
}
}
if(found >= 2) {
String asString = new String(real, "UTF-16");
byte[] newBytes = asString.getBytes("UTF8");
FileOutputStream fos = new FileOutputStream(args[args.length-1]);
fos.write(newBytes);
fos.close();
}
fis.close();
} catch(Exception e) {
e.printStackTrace();
}
皆さんはどう思いますか?