Подтвердить что ты не робот

Как удалить спецификацию из файла XML в Java

Мне нужны предложения по удалению спецификации из файла UTF-8 и созданию копии остальной части xml файла.

4b9b3361

Ответ 1

Наличие разрыва инструмента из-за спецификации в файле UTF-8 - это очень общая вещь в моем опыте. Я не знаю, почему там, где так много downvotes (но тогда это дает мне шанс попытаться получить достаточное количество голосов, чтобы выиграть специальный значок SO;)

Более серьезно: спецификация UTF-8 обычно не имеет такого смысла, но она полностью соответствует (хотя и не рекомендуется) спецификациями. Теперь проблема в том, что многие люди не знают, что спецификация действительна в UTF-8 и, следовательно, написала неработающие инструменты /API, которые не обрабатывают корректно эти файлы.

Теперь у вас могут быть две разные проблемы: вы можете обрабатывать файл с Java или вам нужно использовать Java для программного создания/исправления файлов, которые нужны другим (поврежденным) инструментам.

У меня было дело на одном консультационном концерте, где служба поддержки продолжала получать сообщения от пользователей, у которых были проблемы с каким-то текстовым редактором, который испортил бы совершенно правильные файлы UTF-8, созданные Java. Поэтому мне пришлось обойти эту проблему, убедившись, что вы удаляете спецификацию из каждого файла UTF-8, с которым мы имеем дело.

Я хочу удалить спецификацию из файла, вы можете создать новый файл и пропустить первые три байта. Например:

... $  file  /tmp/src.txt 
/tmp/src.txt: UTF-8 Unicode (with BOM) English text

... $  ls -l  /tmp/src.txt 
-rw-rw-r-- 1 tact tact 1733 2012-03-16 14:29 /tmp/src.txt

... $  hexdump  -C  /tmp/src.txt | head -n 1
00000000  ef bb bf 50 6f 6b 65 ...

Как вы можете видеть, файл начинается с "ef bb bf", это (полностью действительная) спецификация UTF-8.

Вот метод, который берет файл и копирует его, пропуская первые три байта:

 public static void workAroundbrokenToolsAndAPIs(File sourceFile, File destFile) throws IOException {
    if(!destFile.exists()) {
        destFile.createNewFile();
    }

    FileChannel source = null;
    FileChannel destination = null;

    try {
        source = new FileInputStream(sourceFile).getChannel();
        source.position(3);
        destination = new FileOutputStream(destFile).getChannel();
        destination.transferFrom( source, 0, source.size() - 3 );
    }
    finally {
        if(source != null) {
            source.close();
        }
        if(destination != null) {
            destination.close();
        }
    }
}

Обратите внимание, что это "raw": вам обычно нужно сначала убедиться, что у вас есть спецификация перед вызовом этого или "Плохие мысли могут произойти" [TM].

После этого вы можете посмотреть файл:

... $  file  /tmp/dst.txt 
/tmp/dst.txt: UTF-8 Unicode English text

... $  ls -l  /tmp/dst.txt 
-rw-rw-r-- 1 tact tact 1730 2012-03-16 14:41 /tmp/dst.txt

... $  hexdump -C /tmp/dst.txt
00000000  50 6f 6b 65 ...

И спецификация исчезла...

Теперь, если вы просто хотите прозрачно удалить спецификацию для своего сломанного Java-API, вы можете использовать описанный здесь pushbackInputStream: почему org.apache.xerces.parsers.SAXParser делает не пропускать спецификацию в закодированном utf8 xml?

private static InputStream checkForUtf8BOMAndDiscardIfAny(InputStream inputStream) throws IOException {
    PushbackInputStream pushbackInputStream = new PushbackInputStream(new BufferedInputStream(inputStream), 3);
    byte[] bom = new byte[3];
    if (pushbackInputStream.read(bom) != -1) {
        if (!(bom[0] == (byte) 0xEF && bom[1] == (byte) 0xBB && bom[2] == (byte) 0xBF)) {
            pushbackInputStream.unread(bom);
        }
    }
    return pushbackInputStream; }

Обратите внимание, что это работает, но определенно НЕ исправить более серьезную проблему, когда у вас могут быть другие инструменты в рабочей цепочке, которые не работают с UTF-8 файлами, имеющими спецификацию.

А вот ссылка на вопрос с более полным ответом, охватывающая другие кодировки:

Значок байтового байта закручивает чтение файлов в Java