Кодирование Java из UTF-8 в ISO-8859-1 в файл XML

Я пытался преобразовать строку UTF-8 в ее родственник в ISO-8859-1 для вывода ее в XML-документе, и независимо от того, что я пытаюсь, вывод всегда отображается неправильно.

Для упрощения вопроса я создал фрагмент кода со всеми тестами, которые я сделал, и после этого копирую/вставляю сгенерированный документ.

Вы также можете быть уверены, что я пробовал все возможные комбинации между новыми String(xxx.getBytes("UTF-8"), "ISO-8859-1"), переключая UTF и ISO, а иногда также устанавливая одно и то же значение. Ничего не работает!

Вот фрагмент:

// @see http://stackoverflow.com/questions/229015/encoding-conversion-in-java
private static String changeEncoding(String input) throws Exception {
    // Create the encoder and decoder for ISO-8859-1
    Charset charset = Charset.forName("ISO-8859-1");
    CharsetDecoder decoder = charset.newDecoder();
    CharsetEncoder encoder = charset.newEncoder();

    // Convert a string to ISO-LATIN-1 bytes in a ByteBuffer
    // The new ByteBuffer is ready to be read.
    ByteBuffer bbuf = encoder.encode(CharBuffer.wrap(input));

    // Convert ISO-LATIN-1 bytes in a ByteBuffer to a character ByteBuffer and then to a string.
    // The new ByteBuffer is ready to be read.
    CharBuffer cbuf = decoder.decode(bbuf);
    return cbuf.toString();
}

// @see http://stackoverflow.com/questions/655891/converting-utf-8-to-iso-8859-1-in-java-how-to-keep-it-as-single-byte
private static String byteEncoding(String input) throws Exception {
    Charset utf8charset = Charset.forName("UTF-8");
    Charset iso88591charset = Charset.forName("ISO-8859-1");

    ByteBuffer inputBuffer = ByteBuffer.wrap(input.getBytes());

    // decode UTF-8
    CharBuffer data = utf8charset.decode(inputBuffer);

    // encode ISO-8559-1
    ByteBuffer outputBuffer = iso88591charset.encode(data);
    byte[] outputData = outputBuffer.array();
    return new String(outputData, "ISO-8859-1");
}

public static Result home() throws Exception {
    DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
    DocumentBuilder docBuilder = docFactory.newDocumentBuilder();

    //root elements
    Document doc = docBuilder.newDocument();
    doc.setXmlVersion("1.0");
    doc.setXmlStandalone(true);

    Element rootElement = doc.createElement("test");
    doc.appendChild(rootElement);

    rootElement.setAttribute("original", "héllo");

    rootElement.setAttribute("stringToString", new String("héllo".getBytes("UTF-8"), "ISO-8859-1"));

    rootElement.setAttribute("stringToBytes", changeEncoding("héllo"));

    rootElement.setAttribute("stringToBytes2", byteEncoding("héllo"));

    TransformerFactory tf = TransformerFactory.newInstance();
    Transformer transformer = tf.newTransformer();
    transformer.setOutputProperty(OutputKeys.ENCODING, "ISO-8859-1");

    StringWriter writer = new StringWriter();
    transformer.transform(new DOMSource(doc), new StreamResult(writer));
    String output = writer.getBuffer().toString().replaceAll("\n|\r", "");

    // The following is Play!Framework specifics for rendering an url, but I believe this is not the problem (I checked in the developer console, the document is correctly in "ISO-8859-1"
    response().setHeader("Content-Type", "text/xml; charset=ISO-8859-1");
    return ok(output).as("text/xml");
}

И результат:

<?xml version="1.0" encoding="ISO-8859-1"?>
<test original="héllo" stringToBytes="héllo" stringToBytes2="héllo" stringToString="héllo"/>

Как я могу продолжить?


person Cyril N.    schedule 23.02.2014    source источник
comment
Я думаю, что вы неправильно написали response. Если вы говорите о response() из Play!Frameowork, то setCharacterEncoding() нет (я использую Play! 2.1.5). Также нет setCharacterEncoding() в doc` (Документ)   -  person Cyril N.    schedule 23.02.2014
comment
Спасибо за вашу помощь. Я уже установил кодировку ISO-8859-1, вызвав setHeader. В Play v2.1.5 нет encoding (но есть CONTENT_ENCODING, который является окончательным)   -  person Cyril N.    schedule 23.02.2014
comment
Прости еще раз. Я читал 1.2.5, а не 2.1.5.   -  person JB Nizet    schedule 23.02.2014
comment
Никаких проблем ;) Я также пытался использовать только кодировку в ответе http без изменения строк, но это не сработало. Это работает только в том случае, если я также удалю кодировку в документе xml, но это потому, что страница затем отображается как UTF-8, чего я не хочу.   -  person Cyril N.    schedule 23.02.2014
comment
Вы были в чем-то правы. Я, наконец, переключил вывод из StringWriter на запись в файл, а затем вывел этот файл напрямую как двоичный, и теперь все работает нормально, с правильной кодировкой. Никаких переключений кодировки не производилось! Вы можете добавить свои комментарии в качестве ответа, я приму это :)   -  person Cyril N.    schedule 23.02.2014
comment
Вы сделали всю работу, и я не знаю, как превратить это в правильный ответ. Ответьте сами и покажите, что вы сделали. Я нахожу удивительным, что для этого мне приходится просматривать файл, но с Play меня больше ничего не удивляет.   -  person JB Nizet    schedule 23.02.2014


Ответы (1)


По причине, которую я не могу объяснить, запись в файл и возврат этого файла на выход устранила проблему кодирования.

Я решил оставить этот вопрос на случай, если у других людей возникнет аналогичная проблема.

Вот фрагмент:

TransformerFactory tf = TransformerFactory.newInstance();
Transformer transformer = tf.newTransformer();
transformer.setOutputProperty(OutputKeys.ENCODING, "ISO-8859-1");

File file = new File("Path/to/file.xml");
transformer.transform(new DOMSource(doc), new StreamResult(file));

response().setHeader("Content-Disposition", "attachment;filename=" + file.getName());
response().setHeader("Content-Type", "text/xml; charset=ISO-8859-1");
return ok(file).as("text/xml");
person Cyril N.    schedule 24.02.2014