19

What is the best way to add non-ASCII file names to a zip file using Java, in such a way that the files can be properly read in both Windows and Linux?

Here is one attempt, adapted from https://truezip.dev.java.net/tutorial-6.html#Example, which works in Windows Vista but fails in Ubuntu Hardy. In Hardy the file name is shown as abc-ЖДФ.txt in file-roller.

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();
        }
    }
}

Unlike java.util.zip, truezip allows specifying zip file encoding. Here's another sample, this time explicitly specifiying the encoding. Neither IBM437, UTF-8 nor ISO-8859-1 works in Linux. IBM437 works in 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();
        }
    }
}
4

7 に答える 7

10

ZIP 内のファイル エントリのエンコードは、もともと IBM Code Page 437 として指定されています。他の言語で使用される多くの文字は、この方法では使用できません。

PKWARE 仕様は問題を参照し、少し追加します。しかし、それは後の追加です (2007 年から、それを解決してくれた Cheeso に感謝します。コメントを参照してください)。そのビットが設定されている場合、ファイル名エントリは UTF-8 でエンコードする必要があります。この拡張機能については、リンク先のドキュメントの最後にある「APPENDIX D - Language Encoding (EFS)」で説明されています。

Java では、非 ASCII 文字で問題が発生することが既知のバグです。バグ #4244499および多数の関連するバグを参照してください。

私の同僚は、ファイル名を ZIP に保存する前にファイル名の URL エンコードを回避策として使用し、ファイルを読み取った後にデコードしました。保存と読み取りの両方を制御する場合は、回避策になる可能性があります。

編集:バグで、誰かが回避策としてApache AntのZipOutputStreamを使用することを提案しています。この実装では、エンコーディングを指定できます。

于 2008-10-14T11:38:46.793 に答える
8

Zip ファイルでは、PKWare が所有する仕様によると、ファイル名とファイル コメントのエンコードは IBM437 です。2007 年に PKWare は仕様を拡張し、UTF-8 も許可するようにしました。これは、zip 内に含まれるファイルのエンコーディングについては何も述べていません。ファイル名のエンコーディングのみ。

すべてのツールとライブラリ (Java および非 Java) が IBM437 (ASCII のスーパーセット) をサポートし、UTF-8 をサポートするツールとライブラリは少数だと思います。一部のツールとライブラリは、他のコード ページをサポートしています。たとえば、上海で実行されているコンピューターで WinRar を使用して圧縮すると、Big5 コード ページが取得されます。これはzip仕様では「許可」されていませんが、とにかく発生します。

.NET 用のDotNetZipライブラリは Unicode を処理しますが、Java を使用している場合はもちろん役に立ちません!

ZIP の Java 組み込みサポートを使用すると、常に IBM437 を取得できます。IBM437 以外のアーカイブが必要な場合は、サード・パーティーのライブラリーを使用するか、JAR を作成してください。

于 2009-01-04T03:49:48.107 に答える
8

奇跡は実際に起こり、Sun/Oracle は長命のバグ/rfe を実際に修正しました。

zip ファイル/ストリームの作成時にファイル名エンコーディングを設定できるようになりました ( Java 7 が必要)。

于 2010-07-28T11:26:52.740 に答える
7

zip ストリームの Apache Commons実装を引き続き使用できます。%29

ストリームで setEncoding("UTF-8") を呼び出すだけで十分です。

于 2010-12-17T16:03:36.160 に答える
3

TrueZIPマニュアルをざっと見てみると、JAR 形式が推奨されています。

IBM437 のみを使用する ZIP とは異なり、ファイル名のエンコードとコメントに UTF-8 を使用します。

これはおそらく、API がその実装にjava.util.zipパッケージを使用していることを意味します。そのドキュメントには、1996 年からまだ ZIP 形式を使用していると記載されています。Unicode サポートは、2006 年までPKWARE .ZIP ファイル形式仕様に追加されませんでした。

于 2008-09-20T00:09:01.750 に答える
0

Did it actually fail or was just a font issue? (e.g. font having different glyphs for those charcodes) I've seen similar issues in Windows where rendering "broke" because the font didn't support the charset but the data was actually intact and correct.

于 2008-09-19T23:29:16.370 に答える
0

非 ASCII ファイル名は、ZIP 実装全体で信頼性が低く、避けるのが最善です。文字セット設定を ZIP ファイルに格納するための規定はありません。クライアントは「現在のシステム コードページ」を推測する傾向がありますが、これはあなたが望むものである可能性は低いです。クライアントとコードページの多くの組み合わせにより、ファイルにアクセスできなくなる可能性があります。

ごめん!

于 2008-09-19T23:47:22.083 に答える