2013-07-04 75 views
5

Phương thức getResourceAsStream trả về null bất cứ khi nào chạy jar thực thi trong thư mục kết thúc bằng dấu chấm than.Không thể mở tài nguyên trong các thư mục kết thúc bằng dấu chấm than (!)

Đối với ví dụ sau đây, tôi có một dự án Eclipse cấu trúc thư mục sau:

src\ (Source Folder) 
    main\ (Package) 
     Main.java 
    res\ (Source Folder) 
     images\ 
      Logo.png 

Tôi đọc logo.png như sau:

public static void main(String[] args) throws IOException { 
    try (InputStream is = Main.class.getClassLoader().getResourceAsStream("images/Logo.png")) { 
     Image image = ImageIO.read(is); 
     System.out.println(image); 
    } 
} 

Xem tập tin đính kèm trong 2 thử nghiệm các trường hợp. Đầu tiên, jar thực thi được bắt đầu từ thư mục "D: \ test123! @ #" Mà không có bất kỳ vấn đề gì. Thứ hai, các jar thực thi được bắt đầu từ thư mục "D: \ test123! @ # !!!", với các vấn đề.

Các thư mục có dấu chấm than không được hỗ trợ không? Mã có sai không?

Xin cảm ơn trước.

Error when running the executable jar in a directory ending with !

+0

Có lý do nào, bạn có thể tạo/sử dụng các thư mục có tên thông thường không? – mtk

+0

Bạn có chắc chắn rằng bạn đặt các bình bằng nhau trong cả hai thư mục? – Andremoniy

+0

Người dùng có thể thực thi ứng dụng của tôi từ bất cứ đâu trên hệ thống tệp của họ. Thư mục có dấu chấm than được Windows hỗ trợ. – Velth

Trả lời

7

Có lẽ vì lỗi này hoặc bất kỳ của nhiều lỗi tương tự trong cơ sở dữ liệu lỗi Java: "/"

http://bugs.sun.com/view_bug.do?bug_id=4523159

Lý do được rằng trong một URL jar được giải thích là dấu phân tách giữa tên tệp JAR và đường dẫn bên trong chính JAR. Nếu tên thư mục kết thúc bằng!, Chuỗi ký tự "! /" Ở cuối thư mục được giải thích không chính xác. Trong trường hợp của bạn, bạn thực sự đang cố truy cập một tài nguyên có URL sau:

jar: tệp: /// d:/test1231 @ # !!! /test.jar! /images/Logo.png

Lỗi đã được mở trong gần 12 năm và không có khả năng được sửa chữa. Thực ra tôi không biết làm thế nào nó có thể được sửa mà không phá vỡ những thứ khác. Vấn đề là quyết định thiết kế để sử dụng! như nhân vật có một ý nghĩa đặc biệt (tách) trong thức truy cập URL cho các tập tin JAR:

jar:<URL for JAR file>!/<path within the JAR file> 

Kể từ khi dấu chấm than là một ký tự cho phép trong URL, nó có thể xảy ra cả trong URL đến tập tin JAR chính nó, như cũng như trong đường dẫn trong tệp JAR, làm cho nó không thể trong một số trường hợp để tìm ra dấu phân tách "! /" thực tế.

+0

Tôi nhận thấy rằng nó phải làm điều gì đó với Java và phân tích cú pháp các URL bằng "! /", Nhưng tôi không thể tin rằng điều này sẽ là một lỗi. Dù sao, có thể có một giải pháp để giải quyết vấn đề này? – Velth

+0

Không, như đã lưu ý trong lỗi mà tôi liên kết, không có cách giải quyết nhỏ cho vấn đề này. – jarnbjo

1

Một công việc đơn giản xung quanh cho Windows là sử dụng "\" thay vì "/" trong đường dẫn. Điều đó có nghĩa là chuỗi ký tự "! /" Được tìm thấy sau đường dẫn đầy đủ. Ví dụ:

new URL("jar:file:\\d:\\[email protected]#!!!\\test.jar!/images/Logo.png"); 

Mã của tôi:

File jar = new File(jarPath + "/" + jarName); 
URL url = new URL("jar:" + jar.toURI() + "!" + dataFilePath); 
InputStream stream = null; 
try { 
    stream = url.openStream(); 
} catch (FileNotFoundException e) { 
    // Windows fix 
    URL urlFix = new URL("jar:" + jar.toURI().toString().replace('/', '\\') 
     + "!" + dataFilePath); 
    stream = urlFix.openStream(); 
} 

tôi sử dụng toURI() vì nó xử lý những thứ như không gian.

Fixes:

Việc sửa chữa bản thân sẽ cho Java để kiểm tra nếu tập tin tồn tại và nếu không tiếp tục tách tiếp theo (một phần của url "/") cho đến khi tách được kiệt sức, sau đó ném sự ngoại lệ. Vì vậy, nó sẽ thấy rằng "d: \ test1231 @ # !!" ném một java.io.FileNotFoundException và sau đó sẽ thử "d: \ test1231 @ # !!! \ test.jar" không tồn tại. Bằng cách này nó không quan trọng nếu có "!" trong đường dẫn tệp hoặc trong tệp của tệp jar.

Ngoài ra, "! /" Có thể được chuyển sang tên khác là tên tệp bất hợp pháp hoặc một tên cụ thể nào đó (như "jarpath:").

Hoặc làm cho đường dẫn tệp của jar sử dụng thông số khác.

Lưu ý:

Có thể ghi đè lên một cái gì đó, trao đổi một handler, hoặc thay đổi mã để mở file đầu tiên sau đó nhìn bên trong file jar sau đó nhưng tôi đã không nhìn.

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