2009-02-21 70 views
66

Trong ứng dụng java của tôi, tôi cần lấy một số tệp và thư mục.tài nguyên mở với đường dẫn tương đối trong java

Đây là cấu trúc chương trình:

./main.java 
./package1/guiclass.java 
./package1/resources/resourcesloader.java 
./package1/resources/repository/modules/ -> this is the dir I need to get 
./package1/resources/repository/SSL-Key/cert.jks -> this is the file I need to get 

guiclass tải lớp resourcesloader mà sẽ tải các tài nguyên của tôi (thư mục và tập tin).

Giới thiệu về tập tin, tôi đã cố gắng

resourcesloader.class.getClass().getResource("repository/SSL-Key/cert.jks").toString() 

để có được con đường thật, nhưng cách này không hoạt động ...

Về dir Tôi không có ý tưởng làm thế nào để làm .. .

Đề xuất? Cảm ơn.

+1

class.getClass() là không giống như class.getClassLoader(). Có một giải pháp khác nữa, getResourceAsStream() sử dụng một lớp trong cùng một gói với tài nguyên của bạn. Để biết thêm chi tiết: http://tshikatshikaaa.blogspot.nl/2012/07/maven-how-to-access-filesdata-in.html. – JVerstry

+0

Xem thêm http://stackoverflow.com/questions/204784/how-to-construct-a-relative-path-in-java-from-two-absolute-paths-or-urls – Vadzim

Trả lời

37

Cung cấp đường dẫn liên quan đến trình nạp lớp, không phải lớp bạn đang tải bộ nạp. Ví dụ:

resourcesloader.class.getClassLoader().getResource("package1/resources/repository/SSL-Key/cert.jks").toString(); 
1

Làm công việc sau đây?

resourcesloader.class.getClass().getResource("/package1/resources/repository/SSL-Key/cert.jks") 

Có lý do nào bạn không thể chỉ định đường dẫn đầy đủ bao gồm cả gói không?

2
resourcesloader.class.getClass() 

có thể được chia nhỏ để:

Class<resourcesloader> clazz = resourceloader.class; 
Class<Class> classClass = clazz.getClass(); 

Có nghĩa là bạn đang cố gắng để tải các tài nguyên sử dụng một lớp bootstrap.

Thay vào đó bạn có thể muốn một cái gì đó như:

resourcesloader.class.getResource("repository/SSL-Key/cert.jks").toString() 

Nếu chỉ javac cảnh báo về gọi phương pháp tĩnh trên bối cảnh không tĩnh ...

7

Khi bạn sử dụng 'getResource' trên một lớp, một người họ hàng đường dẫn được giải quyết dựa trên gói mà Class đang ở. Khi bạn sử dụng 'getResource' trên một ClassLoader, một đường dẫn tương đối được giải quyết dựa trên thư mục gốc.

Nếu bạn sử dụng đường dẫn tuyệt đối, cả hai phương thức 'getResource' sẽ bắt đầu tại thư mục gốc.

+0

Đừng quên tác dụng của '' '/' '' – Gilberto

+0

@nbeyer Tại sao sử dụng 'getResource' với đường dẫn bắt đầu tuyệt đối tại thư mục gốc? Không phải là mục đích của đường dẫn tuyệt đối ** tuyệt đối **? –

126

Tôi gặp sự cố khi sử dụng phương thức getClass().getResource("filename.txt"). Khi đọc hướng dẫn tài liệu Java, nếu tài nguyên của bạn không nằm trong cùng gói với lớp bạn đang cố truy cập tài nguyên, thì bạn phải cung cấp cho nó đường dẫn tương đối bắt đầu bằng '/'. Chiến lược được đề xuất là đặt các tệp tài nguyên của bạn trong thư mục "tài nguyên" trong thư mục gốc.Vì vậy, ví dụ nếu bạn có cấu trúc:

src/main/com/mycompany/myapp 

sau đó bạn có thể thêm một thư mục nguồn lực theo khuyến cáo của maven trong:

src/main/resources 

hơn nữa bạn có thể thêm các thư mục con trong thư mục nguồn

src/main/resources/textfiles 

và nói rằng tệp của bạn được gọi là myfile.txt để bạn có

src/main/resources/textfiles/myfile.txt 

Bây giờ, đây là nơi có vấn đề về đường dẫn ngu ngốc. Giả sử bạn có một lớp trong số com.mycompany.myapp package và bạn muốn truy cập tệp myfile.txt từ thư mục tài nguyên của mình. Một số người nói bạn cần phải cung cấp cho các:

"/main/resources/textfiles/myfile.txt" path 

hoặc

"/resources/textfiles/myfile.txt" 

cả trong số này là sai. Sau khi tôi chạy mvn clean compile, các tệp và thư mục được sao chép trong:

myapp/target/classes 

thư mục. Nhưng thư mục tài nguyên không có ở đó, chỉ các thư mục trong thư mục tài nguyên. Vì vậy, bạn có:

myapp/target/classes/textfiles/myfile.txt 

myapp/target/classes/com/mycompany/myapp/* 

nên đường dẫn chính xác để cung cấp cho các phương pháp getClass().getResource("") là:

"/textfiles/myfile.txt" 

ở đây là:

getClass().getResource("/textfiles/myfile.txt") 

này sẽ không còn trở về null, nhưng sẽ trả lại lớp học của bạn. Tôi hy vọng điều này sẽ giúp ai đó. Điều lạ lùng với tôi là thư mục "resources" cũng không được sao chép, mà chỉ là các thư mục con và tệp trực tiếp trong thư mục "resources". Nó có vẻ hợp lý với tôi rằng thư mục "resources" cũng sẽ được tìm thấy dưới "myapp/target/classes"

+1

Trong 'target/classes' của tôi, tôi chỉ có thể xem các tệp trong tài nguyên chính và không kiểm tra tài nguyên. Tại sao? – Ava

+0

@Ava Thêm thư mục thử nghiệm làm thư mục nguồn của bạn và bạn tốt để đi! –

8

@GianCarlo: Bạn có thể thử gọi System property user.dir sẽ cung cấp cho bạn gốc của dự án java của bạn và sau đó thêm đường dẫn này vào đường dẫn tương đối ví dụ:

String root = System.getProperty("user.dir"); 
String filepath = "/path/to/yourfile.txt"; // in case of Windows: "\\path \\to\\yourfile.txt 
String abspath = root+filepath; 



// using above path read your file into byte [] 
File file = new File(abspath); 
FileInputStream fis = new FileInputStream(file); 
byte []filebytes = new byte[(int)file.length()]; 
fis.read(filebytes); 
+0

OP muốn định vị một tài nguyên trong classpath (rất có thể trong một jar được tạo trong lần xây dựng thứ hai). Phương pháp này không cung cấp cách để đạt được mục tiêu đó - bạn không thể trỏ một tệp 'vào một tài nguyên bên trong tệp jar, chỉ với mục nhập thích hợp trong hệ thống tệp (ví dụ: bản thân cái bình). – Attila

29

trong hy vọng cung cấp thêm thông tin cho những người không chọn này lên càng nhanh như những người khác, tôi muốn cung cấp kịch bản của tôi vì nó có một thiết lập hơi khác nhau. Dự án của tôi là thiết lập với cấu trúc thư mục sau (sử dụng Eclipse):

 
Project/ 
    src/    // application source code 
    org/ 
     myproject/ 
     MyClass.java 
    test/    // unit tests 
    res/    // resources 
    images/   // PNG images for icons 
     my-image.png 
    xml/    // XSD files for validating XML files with JAXB 
     my-schema.xsd 
    conf/    // default .conf file for Log4j 
     log4j.conf 
    lib/    // libraries added to build-path via project settings 

Tôi đã có vấn đề tải nguồn lực của tôi từ res thư mục. Tôi muốn tất cả các tài nguyên của tôi tách biệt với mã nguồn của tôi (chỉ đơn giản là cho mục đích quản lý/tổ chức).Vì vậy, những gì tôi phải làm là thêm res thư mục vào xây dựng con đường và sau đó truy cập vào tài nguyên qua:

static final ClassLoader loader = MyClass.class.getClassLoader(); 

// in some function 
loader.getResource("images/my-image.png"); 
loader.getResource("xml/my-schema.xsd"); 
loader.getResource("conf/log4j.conf"); 

LƯU Ý: Các / được bỏ qua từ khi bắt đầu chuỗi tài nguyên vì tôi đang sử dụng ClassLoader.getResource(String) thay vì Class.getResource(String).

+1

. + 1 để đề xuất ClassLoader – pyb

+0

Câu trả lời hay nhất về chủ đề này! Mẹo không sử dụng '/' ở đầu đường dẫn tài nguyên là chìa khóa! – Kayhadrin

1

Đi với hai câu trả lời như đã đề cập ở trên. Người đầu tiên

resourcesloader.class.getClassLoader().getResource("package1/resources/repository/SSL-Key/cert.jks").toString(); 
resourcesloader.class.getResource("repository/SSL-Key/cert.jks").toString() 

Nên là một điều tương tự?

3

Đối với những người sử dụng eclipse + maven. Giả sử bạn thử truy cập tệp images/pic.jpg trong src/main/resources. Làm theo cách này:

ClassLoader loader = MyClass.class.getClassLoader(); 
File file = new File(loader.getResource("images/pic.jpg").getFile()); 

là hoàn toàn chính xác nhưng có thể dẫn đến ngoại lệ con trỏ null. Có vẻ như nhật thực không nhận ra các thư mục trong cấu trúc thư mục maven như các thư mục nguồn ngay lập tức. Bằng cách loại bỏ và thư mục src/main/resources từ danh sách thư mục nguồn của dự án và đưa nó trở lại (project> properties> đường dẫn xây dựng java> source> remove/add Folder), tôi đã có thể giải quyết vấn đề này.

0

Tôi đã sửa đổi nhỏ trên một lớp lót của @ jonathan.cone (bằng cách thêm .getFile()) để tránh ngoại lệ con trỏ null và đặt đường dẫn đến thư mục dữ liệu. Đây là những gì làm việc cho tôi:

String realmID = new java.util.Scanner(new java.io.File(RandomDataGenerator.class.getClassLoader().getResource("data/aa-qa-id.csv").getFile().toString())).next(); 
0

Sử dụng này:

resourcesloader.class.getClassLoader().getResource("/path/to/file").**getPath();** 
Các vấn đề liên quan