2008-09-19 4 views
19

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

Это попытка, выполненная из 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(); 
     } 
    } 
} 
+0

truezip с UTF-8 работал для меня на окнах 7 и mac os x 10.6.x. Он все еще не работает в Linux? – 2009-11-23 17:37:34

+1

Была давняя ошибка - 9 лет существования - в JDK до версии v7, которая предотвратила правильную обработку имен файлов с именами, которые не могли быть закодированы с помощью IBM CP437. http://bugs.sun.com/bugdatabase/view_bug.do?bug%5Fid=4244499 Он, по-видимому, был исправлен в JDK7. https://blogs.oracle.com/xuemingshen/entry/non_utf_8_encoding_in Поэтому одним из решений является использование JDK7 и новых конструкторов для ZipInputStream, ZipOutputStream и ZipFile. – Cheeso 2012-06-15 16:53:56

ответ

0

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

+0

Спасибо за ваш ответ, это не проблема с шрифтом, потому что я могу создать файл с аналогичным именем, а затем закрепить его, и он будет отображаться правильно. – Micke 2008-09-19 23:36:05

0

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

Извините!

+0

Согласно спецификации PKWare, есть положение о том, что указанное имя файла кодируется UTF-8. Кодировка UTF-8 в zip-файлах еще не получила широкого распространения (== еще не поддерживается в проводнике Windows). Когда бит UTF-8 не установлен в заголовке записи zip, спецификация zip указывает, что имя файла должно быть закодировано в IBM437. Но вы правы, некоторые приложения (WinRar) просто кодируются с кодовой страницей по умолчанию. Не уверен, что Windows Explorer делает это. Неправильное кодирование при чтении zip может привести к недоступным файлам. – Cheeso 2009-05-19 15:20:59

3

Из беглого взгляда на TrueZIP manual - они рекомендуют формат JAR:

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

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

10

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

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

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

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

EDIT: при ошибке кто-то предлагает использовать ZipOutputStream от Apache Ant в качестве обходного пути. Эта реализация позволяет специфицировать кодировку.

+0

«Похоже, что это исторически указано, как IBM CP437» немного расплывчато. Спецификация PKWare говорит, что имена файлов используют IBM437 для кодирования, периода. В 2007 году PKWare добавила стандартный способ использования UTF-8. Есть инструменты, которые не используют ни одного, но это вне спецификации! – Cheeso 2009-03-28 08:22:45

+1

Спасибо за разъяснение, я изменил ответ. – Mnementh 2009-03-30 11:33:23

8

В 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.

8

Чудеса действительно случаются, и Sun/Oracle на самом деле исправить долгоживущего ошибка/RFE:

Теперь можно set up filename encodings upon creating почтовый файл/поток (требует Java 7).