我有一个文件观察器,它从一个使用 utf-16LE 编码的不断增长的文件中获取内容。写入它的第一个数据位具有可用的 BOM——我使用它来识别针对 UTF-8 的编码(我的大部分文件都是用其中编码的)。我捕获了 BOM 并重新编码为 UTF-8,这样我的解析器就不会崩溃。问题在于,由于它是一个不断增长的文件,因此并非所有数据都包含 BOM。
这是我的问题 - 如果不将 BOM 字节添加到我拥有的每组数据(因为我无法控制源),我可以只查找 UTF-16 \000 中固有的空字节,然后使用那作为我的标识符而不是BOM?这会让我头疼吗?
我的架构涉及一个 ruby Web 应用程序,当我用 java 编写的解析器拾取它时,将接收到的数据记录到一个临时文件中。
现在写我的识别/重新编码代码如下所示:
// 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();
}
更新
我想支持欧元、破折号和其他字符之类的东西。我修改了上面的代码看起来像这样,它似乎通过了我对这些字符的所有测试:
// 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();
}
大家怎么看?