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

Добавьте имена файлов, отличных от ASCII, в zip в Java

Каков наилучший способ добавить имена файлов не-ASCII в zip файл с помощью Java, таким образом, чтобы файлы могут быть правильно прочитаны как в Windows, так и Linux?

Вот одна попытка, адаптированная из https://truezip.dev.java.net/tutorial-6.html#Example, которая работает в Windows Vista, но не работает в Ubuntu Hardy. В Hardy имя файла отображается как abc-ЖДФ .txt в файле-ролике.

import java.io.IOException;
import java.io.PrintStream;

import de.schlichtherle.io.File;
import de.schlichtherle.io.FileOutputStream;

public class Main {

    public static void main(final String[] args) throws IOException {

        try {
            PrintStream ps = new PrintStream(new FileOutputStream(
                    "outer.zip/abc-åäö.txt"));
            try {
                ps.println("The characters åäö works here though.");
            } finally {
                ps.close();
            }
        } finally {
            File.umount();
        }
    }
}

В отличие от java.util.zip, truezip позволяет указать кодировку zip файла. Здесь еще один пример, на этот раз явно указывающий кодировку. В Linux не работают ни IBM437, ни UTF-8, ни ISO-8859-1. IBM437 работает в Windows.

import java.io.IOException;

import de.schlichtherle.io.FileOutputStream;
import de.schlichtherle.util.zip.ZipEntry;
import de.schlichtherle.util.zip.ZipOutputStream;

public class Main {

    public static void main(final String[] args) throws IOException {

        for (String encoding : new String[] { "IBM437", "UTF-8", "ISO-8859-1" }) {
            ZipOutputStream zipOutput = new ZipOutputStream(
                    new FileOutputStream(encoding + "-example.zip"), encoding);
            ZipEntry entry = new ZipEntry("abc-åäö.txt");
            zipOutput.putNextEntry(entry);
            zipOutput.closeEntry();
            zipOutput.close();
        }
    }
}
4b9b3361

Ответ 1

Кодирование файлов-записей в ZIP-каталоге изначально указано как код IBM Code Page 437. Многие символы, используемые на других языках, невозможно использовать таким образом.

PKWARE-спецификация относится к проблеме и добавляет немного. Но это более позднее дополнение (с 2007 года, благодаря Cheeso для его устранения, см. Комментарии). Если этот бит установлен, запись имени файла должна быть закодирована в UTF-8. Это расширение описано в "ПРИЛОЖЕНИЕ D - кодирование языка (EFS)", которое находится в конце связанного документа.

Для Java это известная ошибка, чтобы попасть в проблему с не-ASCII-символами. См. ошибка # 4244499 и большое количество связанных ошибок.

Мой коллега использовал в качестве обходного URL-кодирования для имен файлов, прежде чем хранить их в ZIP и расшифровать после их прочтения. Если вы контролируете как хранение, так и чтение, это может быть обходным способом.

РЕДАКТИРОВАТЬ: при ошибке кто-то предлагает использовать ZipOutputStream из Apache Ant в качестве обходного пути. Эта реализация позволяет специфицировать кодировку.

Ответ 2

В Zip файлах, согласно спецификации, принадлежащей PKWare, кодирование имен файлов и комментариев к файлам - IBM437. В 2007 году PKWare расширила спецификацию, чтобы разрешить UTF-8. Это ничего не говорит о кодировании файлов, содержащихся в zip. Только кодировка имен файлов.

Я думаю, что все инструменты и библиотеки (Java и не Java) поддерживают IBM437 (который является надмножеством ASCII), а меньшее количество инструментов и библиотек поддерживают UTF-8. Некоторые инструменты и библиотеки поддерживают другие кодовые страницы. Например, если вы заархивируете что-то с помощью WinRar на компьютере, работающем в Шанхае, вы получите кодовую страницу Big5. Это не "разрешено" спецификацией zip, но это все равно.

Библиотека DotNetZip для .NET делает Unicode, но, конечно, это не поможет вам, если вы используете Java!

Используя встроенную поддержку Java для ZIP, вы всегда получите IBM437. Если вам нужен архив с чем-то другим, кроме IBM437, используйте стороннюю библиотеку или создайте JAR.

Ответ 5

С быстрым просмотром TrueZIP manual - они рекомендуют формат JAR:

Он использует UTF-8 для кодирования имени файла и комментарии - в отличие от ZIP, который только использует IBM437.

Это, вероятно, означает, что API использует java.util.zip пакет для его реализации; эта документация утверждает, что она по-прежнему использует ZIP-формат с 1996 года. Поддержка Unicode не была добавлена ​​в PKWARE. Формат файла формата ZIP до 2006 года.

Ответ 6

Неужели это на самом деле закончилось неудачей или просто проблема с шрифтом? (например, шрифт с разными глифами для этих кодов). Я видел подобные проблемы в Windows, где рендеринг "сломался", потому что шрифт не поддерживал кодировку, но данные были фактически неповрежденными и правильными.

Ответ 7

Имена файлов, отличных от ASCII, не являются надежными в реализациях ZIP, и их лучше избегать. В файлах ZIP не предусмотрено сохранение настроек кодировки; клиенты склонны угадывать "текущую кодовую страницу системы", которая вряд ли будет тем, что вы хотите. Многие комбинации кликов и кодовых страниц могут привести к недоступным файлам.

К сожалению!