У меня есть наблюдатель файлов, который захватывает контент из растущего файла, закодированного с помощью utf-16LE. Первый бит записанных в него данных имеет доступную спецификацию - я использовал ее, чтобы идентифицировать кодировку по UTF-8 (в которой закодировано БОЛЬШИНСТВО моих файлов). Я ловлю спецификацию и перекодирую в UTF-8, чтобы мой синтаксический анализатор не волновался. Проблема в том, что, поскольку это растущий файл, не каждый бит данных содержит спецификацию.
Вот мой вопрос - не добавляя байты спецификации к каждому набору данных, которые у меня есть (потому что у меня нет контроля над источником), могу ли я просто искать нулевые байты, которые присущи UTF- 16 \ 000, а затем использовать это как мой идентификатор вместо спецификации? Будет ли это вызывать у меня головные боли в будущем?
Моя архитектура включает в себя рубиновое веб-приложение, записывающее полученные данные во временный файл, когда мой синтаксический анализатор, написанный на 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();
}
Что вы все думаете?