Как писать китайские иероглифы в ZipEntry? - PullRequest
0 голосов
/ 31 октября 2019

Я хочу экспортировать строку (китайский текст) в файл CSV внутри zip-файла. Где мне нужно установить кодировку UTF-8? Или какой подход следует использовать (на основе приведенного ниже кода) для отображения китайских символов в экспортированном файле CSV?

Это код, который у меня есть в настоящее время.

        ByteArrayOutputStream out = new ByteArrayOutputStream();
        ZipOutputStream zipOut = new ZipOutputStream(out, StandardCharsets.UTF_8)
        try {
            ZipEntry entry = new ZipEntry("chinese.csv");
            zipOut.putNextEntry(entry);
            zipOut.write("类型".getBytes());
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            zipOut.close();
            out.close();
        }

Вместо """, Я получаю" ç ± »åž‹ "в файле CSV.

Ответы [ 2 ]

1 голос
/ 31 октября 2019

Метод getBytes() является одним из преступников, без явной кодировки он принимает набор символов по умолчанию вашего компьютера. Начиная с документации Java String:

getBytes()
Кодирует эту строку в последовательность байтов, используя платформыкодировка по умолчанию , сохраняющая результат в новом байтовом массиве.

getBytes(string charsetName)
Кодирует эту строку в последовательность байтов, используя заданную кодировку , сохраняя результат в новом байтовом массиве.

Кроме того, как указал @Slaw, убедитесь, что вы компилируете (javac -encoding <encoding>) своих файлов с той же кодировкойфайлы находятся в:

-encoding Установите имя кодировки исходного файла, например, EUC-JP и UTF-8. Если -encoding не указан, используется конвертер платформы по умолчанию.

В операции OP отсутствует вызов closeEntry(). Я разделил фрагмент до того, что мне показалось необходимым для достижения желаемой функциональности.

    try (FileOutputStream fileOut = new FileOutputStream("out.zip");
         ZipOutputStream zipOut = new ZipOutputStream(fileOut)) {
        zipOut.putNextEntry(new ZipEntry("chinese.csv"));
        zipOut.write("类型".getBytes("UTF-8"));
        zipOut.closeEntry();
    }

Наконец, как указал @MichaelGantman, вы можете проверить, в каком кодировании используется инструмент, такой как hex-редактор, например, также исключить, что редактор просматривает файл результатов. на дисплеях неверно указан utf-8. "类" в utf-8 равно (hex) e7 b1 bb в utf-16 (кодировка java по умолчанию) это 7c 7b

0 голосов
/ 31 октября 2019

Во-первых, вам определенно необходимо изменить zipOut.write("类型".getBytes()); на zipOut.write("类型".getBytes(StandardCharsets.UTF_8)); Кроме того, когда вы открываете результирующий CSV-файл, редактор может не знать, что содержимое закодировано в UTF-8. Возможно, вам придется сообщить вашему редактору, что это кодировка UTF-8. Например, в Блокноте вы можете сохранить свой файл с опцией «Сохранить как» и изменить кодировку на UTF-8. Кроме того, ваша проблема может быть просто неправильная проблема отображения, а не фактическая кодировка. Существует библиотека Java с открытым исходным кодом, в которой есть утилита, которая преобразует любую строку в последовательность Unicode и наоборот. Эта утилита помогала мне много раз, когда я работал над диагностикой различных проблем, связанных с кодировкой. Вот пример того, что делает код

result = "Hello World";
result = StringUnicodeEncoderDecoder.encodeStringToUnicodeSequence(result);
System.out.println(result);
result = StringUnicodeEncoderDecoder.decodeUnicodeSequenceToString(result);
System.out.println(result);

Вывод этого кода:

\u0048\u0065\u006c\u006c\u006f\u0020\u0057\u006f\u0072\u006c\u0064
Hello World

Библиотека может быть найдена в Maven Central или в Github Он поставляется как артефакт maven и содержит источники и javadoc

Вот javadoc для класса StringUnicodeEncoderDecoder

Я попробовал ваши данные и получил это:

System.out.println(StringUnicodeEncoderDecoder.encodeStringToUnicodeSequence("类型"));
System.out.println(StringUnicodeEncoderDecoder.encodeStringToUnicodeSequence("类型"));

И вывод был:

\u7c7b\u578b
\u00e7\u00b1\u00bb\u00e5\u017e\u2039

Похоже, вы потеряли информацию, и это не просто проблема с отображением

...