2008-09-19 26 views
19

gì là cách tốt nhất để thêm phi ASCII tên tập tin vào một tập tin zip sử dụng Java, trong một cách mà các tập tin có thể được đúng đọc cả hai WindowsLinux?Thêm tên file không ASCII để zip trong Java

Đây là một lần thử, được điều chỉnh từ https://truezip.dev.java.net/tutorial-6.html#Example, hoạt động trong Windows Vista nhưng không hoạt động trong Ubuntu Hardy. Trong Hardy tên tệp được hiển thị dưới dạng abc-ЖДФ.txt trong tệp-con lăn.

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

Không giống như java.util.zip, truezip cho phép chỉ định mã hóa tệp zip. Đây là một mẫu khác, lần này xác định rõ ràng mã hóa. Cả IBM437, UTF-8 lẫn ISO-8859-1 đều không hoạt động trong Linux. IBM437 hoạt động trong 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 với UTF-8 làm việc cho tôi trên windows 7 và mac os x 10.6.x. Nó vẫn không hoạt động trong Linux? –

+1

Đã có một lỗi lâu đời - 9 năm tồn tại - trong JDK trước phiên bản 7 đã ngăn cản việc xử lý đúng tên tệp với các tên không thể mã hóa bằng CP437 của IBM. http://bugs.sun.com/bugdatabase/view_bug.do?bug%5Fid=4244499 Nó rõ ràng đã được sửa trong JDK7. https://blogs.oracle.com/xuemingshen/entry/non_utf_8_encoding_in Vì vậy, một giải pháp có vẻ là, sử dụng JDK7 và các nhà xây dựng mới cho ZipInputStream, ZipOutputStream và ZipFile. – Cheeso

Trả lời

0

Đã thực sự thất bại hay chỉ là vấn đề về phông chữ? (ví dụ: phông chữ có các glyph khác nhau cho các mã đó) Tôi đã thấy các sự cố tương tự trong Windows, nơi hiển thị "đã bị hỏng" do phông chữ không hỗ trợ bộ ký tự nhưng dữ liệu thực sự nguyên vẹn và chính xác.

+0

Cảm ơn bạn đã trả lời, nó không phải là một vấn đề phông chữ vì tôi có thể tạo một tệp có tên tương tự và sau đó nén nó và nó sẽ hiển thị đúng. – Micke

0

Tên tệp không phải ASCII không đáng tin cậy trong việc triển khai ZIP và tốt nhất nên tránh. Không có điều khoản để lưu trữ cài đặt bộ ký tự trong các tệp ZIP; khách hàng có xu hướng đoán với 'hệ thống mã hiện tại', điều này dường như không phải là những gì bạn muốn. Nhiều kết hợp của client và codepage có thể dẫn đến các file không thể truy cập được.

Xin lỗi!

+0

Theo thông số kỹ thuật của PKWare, có một điều khoản để lưu ý rằng tên tệp được đề cập được mã hóa bằng UTF-8. Mã hóa UTF-8 trong các tệp zip chưa được hỗ trợ rộng rãi (== chưa được hỗ trợ trong Windows Explorer). Khi bit UTF-8 không được đặt trong tiêu đề mục nhập zip, thông số zip cho biết tên tệp phải được mã hóa trong IBM437. Nhưng bạn là chính xác, một số ứng dụng (WinRar) chỉ mã hóa với trang mã mặc định của hệ thống. Không chắc chắn nếu Windows Explorer thực hiện điều này. Không sử dụng mã hóa thích hợp khi đọc một tệp zip thực tế có thể dẫn đến các tệp không thể truy cập được. – Cheeso

3

Từ một cái nhìn nhanh chóng tại TrueZIP manual - họ giới thiệu các định dạng JAR:

Nó sử dụng UTF-8 cho tên tập tin mã hóa và bình luận - không giống như bưu điện, mà chỉ sử dụng IBM437.

Điều này có thể có nghĩa là API đang sử dụng gói java.util.zip để triển khai; tài liệu đó nói rằng nó vẫn đang sử dụng ZIP format from 1996. Hỗ trợ Unicode chưa được thêm vào PKWARE .ZIP File Format Specification cho đến năm 2006.

10

Mã hóa cho Tệp-mục nhập trong ZIP ban đầu được chỉ định là Mã IBM 437. Nhiều ký tự được sử dụng bằng các ngôn ngữ khác không thể sử dụng theo cách đó.

PKWARE-specification đề cập đến sự cố và thêm một chút. Nhưng đó là một bổ sung sau này (từ năm 2007, nhờ có Cheeso để dọn dẹp, xem bình luận). Nếu bit đó được đặt, mục nhập tên tệp phải được mã hóa bằng UTF-8. Phần mở rộng này được mô tả trong 'PHỤ LỤC D - Mã hóa ngôn ngữ (EFS)', đó là ở phần cuối của tài liệu được liên kết.

Đối với Java, đó là lỗi đã biết, gặp rắc rối với các ký tự không phải ASCII. Xem bug #4244499 và số lượng lỗi liên quan cao.

Đồng nghiệp của tôi được sử dụng làm URL giải mã-Mã hóa cho tên tệp trước khi lưu trữ chúng vào ZIP và giải mã sau khi đọc chúng. Nếu bạn kiểm soát cả hai, lưu trữ và đọc, đó có thể là một cách giải quyết khác.

EDIT: Tại lỗi, người nào đó đề xuất sử dụng ZipOutputStream từ Apache Ant như giải pháp thay thế. Việc triển khai này cho phép đặc tả mã hóa.

+0

"Dường như được xác định trong lịch sử như IBM CP437" hơi lỏng lẻo. Thông số PKWare nói rằng tên tập tin sử dụng IBM437 cho giai đoạn mã hóa. Trong năm 2007, PKWare đã thêm một cách tiêu chuẩn để sử dụng UTF-8. Có những công cụ không sử dụng, nhưng đó là bên ngoài spec! – Cheeso

+1

Cảm ơn bạn đã làm rõ, tôi đã thay đổi câu trả lời. – Mnementh

+1

bạn đã viết "nếu bit đó được đặt, tất cả các mục nhập tên tệp phải được mã hóa bằng UTF-8". Điều này LAF không đúng. Việc sử dụng UTF-8 hoặc IBM437 là mỗi lần nhập, không phải cho mỗi lưu trữ. Tệp zip tuân thủ đặc tả có thể chứa một số mục nhập có tên được mã hóa bằng UTF-8 và các tên khác được mã hóa trong IBM437. – Cheeso

8

Trong tệp Zip, theo thông số kỹ thuật do PKWare sở hữu, việc mã hóa tên tệp và nhận xét tệp là IBM437. Trong năm 2007, PKWare đã mở rộng đặc tả để cho phép UTF-8. Điều này không nói gì về việc mã hóa các tệp có trong zip. Chỉ mã hóa tên tệp.

Tôi nghĩ rằng tất cả các công cụ và thư viện (Java và không Java) đều hỗ trợ IBM437 (là phần mềm hỗ trợ ASCII) và ít công cụ và thư viện hỗ trợ UTF-8 hơn. Một số công cụ và libs hỗ trợ các trang mã khác. Ví dụ, nếu bạn nén một cái gì đó bằng cách sử dụng WinRar trên một máy tính chạy ở Thượng Hải, bạn sẽ nhận được trang mã Big5. Điều này không được "cho phép" bởi thông số zip nhưng nó vẫn xảy ra.

Thư viện DotNetZip cho .NET. Unicode, nhưng tất nhiên điều đó không giúp bạn nếu bạn đang sử dụng Java!

Sử dụng hỗ trợ Java tích hợp sẵn cho ZIP, bạn sẽ luôn nhận được IBM437. Nếu bạn muốn lưu trữ với một cái gì đó khác với IBM437, thì hãy sử dụng thư viện của bên thứ ba hoặc tạo một JAR.

+2

Tại sao lại bỏ phiếu ẩn danh? Bạn không thích thông tin chính xác? – Cheeso

+2

Tôi vẫn không chắc tại sao câu trả lời này lại bị giảm giá. Đó là * vẫn * thông tin chính xác và chính xác. Nếu có ai phản đối, hoặc nếu có ai nghĩ rằng thông tin trong câu trả lời này là sai, xin hãy lên tiếng. – Cheeso

8

Miracles thực sự xảy ra, và Sun/Oracle đã thực sự sửa chữa dài sống lỗi/RFE:

Bây giờ nó có thể set up filename encodings upon creating file zip/dòng (yêu cầu Java 7).

+0

Liên kết đó đã chết http: //img819.imageshack.us/img819/4199/croppercapture6l.jpg – Cheeso

+2

Đây là bài đăng trên blog, hoạt động vào tháng 6 năm 2012, về Miracle: https://blogs.oracle.com/xuemingshen/entry/non_utf_8_encoding_in – Cheeso

Các vấn đề liên quan