Java XMLStreamWriter сериализует '£' как разные байтовые данные в модульном тесте сборки maven (в Windows) - PullRequest
0 голосов
/ 11 июня 2019

В следующем модульном тесте для создания простого XML-документа используется API Java XML.

import org.junit.Test;

import javax.xml.stream.*;
import java.io.ByteArrayOutputStream;

public class XmlErrorTest {
    @Test
    public void test() throws XMLStreamException {

        final XMLOutputFactory xmlOutFact = XMLOutputFactory.newInstance();    
        final ByteArrayOutputStream baos = new ByteArrayOutputStream();
        final XMLStreamWriter xwtr = xmlOutFact.createXMLStreamWriter(baos);

        xwtr.writeStartDocument();
        xwtr.writeStartElement("Test");
        xwtr.writeCharacters(Character.toString('£'));
        xwtr.writeEndElement();
        xwtr.writeEndDocument();

        xwtr.close();

        System.out.println(baos.toString());
        final byte[] bs = baos.toByteArray();
        for (int i = 27; i < 31; ++i) {
            System.out.println(i + " : " + bs[i] + "(" + (char)bs[i] + ")");
        }
    }
}

Если я запускаю тест непосредственно с IDE (Intellij), он выдает следующее:

<?xml version="1.0" ?><Test>£</Test>
27 : 62(>)
28 : -62(ᅡ)
29 : -93(ᆪ)
30 : 60(<)

Т.е. символ £ правильно воспроизводится в выходных данных.Если я запускаю тест в сборке Maven, то получаю следующее:

<?xml version="1.0" ?><Test>�</Test>
27 : 62(>)
28 : -93(?)
29 : 60(<)
30 : 47(/)

Т.е. сгенерированные байтовые данные кажутся неверными - похоже, они сбрасывают байт.

Обратите внимание, яЯ указываю следующее в родительском файле pom.xml:

<properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>

Почему символ XML £ «поврежден» при запуске теста из Maven?Это происходит только в Windows - сборки Linux и MacOS кажутся неосуществленными.

Это с Java 1.8.0_131 и Maven 3.3.9.

Ответы [ 2 ]

2 голосов
/ 11 июня 2019

вы можете попробовать обернуть OutputStream в Writer с указанной кодировкой:

final ByteArrayOutputStream baos = new ByteArrayOutputStream();
final OutputStreamWriter stringWriter = new OutputStreamWriter(baos, StandardCharsets.UTF_8);
final XMLStreamWriter xwtr = xmlOutFact.createXMLStreamWriter(stringWriter);

Причина заключается в кодировке JVM по умолчанию, когда вы работаете с IntelliJ, он запускается с добавленным параметром -Dfile.encoding = UTF-8.

Вы можете проверить текущую кодировку, используя это:

Charset defaultCharset = Charset.defaultCharset();
System.out.println(defaultCharset);

Вы можете добавить -Dfile.encoding = UTF-8 в maven при запуске, но IMHO, мы не должны зависеть от кодировки по умолчанию, всегда указывайте кодировку при работе с байтовым / строковым преобразованием. Пример: Вместо:

//using default charset, we cannot know in runtime    
"test".getBytes();
String foo = new String(bytes);
Reader reader = new FileReader(file);

Просто используйте это:

"test".getBytes(StandardCharsets.UTF_8);
String foo = new String(bytes, StandardCharsets.UTF_8);
Reader reader = new InputStreamReader(new FileInputStream(file),"UTF-8");
1 голос
/ 11 июня 2019

Плагин maven surefire использует кодировку вашей системы.

Таким образом, вы должны закодировать это так же:

    final XMLOutputFactory xmlOutFact = XMLOutputFactory.newInstance();    
    final ByteArrayOutputStream baos = new ByteArrayOutputStream();
    final XMLStreamWriter xwtr = xmlOutFact.createXMLStreamWriter(baos, "ISO-8859-1");

    xwtr.writeStartDocument("ISO-8859-1", "1.0");

Или вы предпочитаете настроить плагин surefire для использования UTF-8:

            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-surefire-plugin</artifactId>
                <version>3.0.0-M3</version>
                <configuration>
                    <argLine>-Dfile.encoding=UTF-8</argLine>
                </configuration>
            </plugin>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...