2011-12-15 39 views
6

Tôi có hai thư mục tài nguyên.Tạo tệp trong tài nguyên/thư mục nguồn trong java theo lập trình?

src - đây là file java của tôi

nguồn lực - đây là file nguồn của tôi (hình ảnh, .properties) tổ chức trong các thư mục (gói).

Có cách nào để lập trình thêm tệp .properties khác trong thư mục tài nguyên đó không?

tôi đã cố gắng một cái gì đó như thế này:

public static void savePropertiesToFile(Properties properties, File propertiesFile) throws IOException { 
     FileOutputStream out = new FileOutputStream(propertiesFile); 
     properties.store(out, null); 
     out.close(); 
    } 

và trước đó tạo:

new File("/folderInResources/newProperties.properties"); 

Nhưng có vẻ cho rằng đường dẫn trên hệ thống tập tin. Làm thế nào tôi có thể buộc nó nhìn vào thư mục tài nguyên?

EDIT: Hãy để tôi nói nó là gì. Tôi có một ứng dụng GUI và tôi hỗ trợ 2 ngôn ngữ (2 tệp .properties trong thư mục tài nguyên). Bây giờ tôi đã thêm một tùy chọn mà người dùng có thể dễ dàng dịch ứng dụng và khi anh ấy kết thúc, tôi lưu các tệp .properties mới trên một đĩa trong một số thư mục ẩn và đọc nó từ đó. Nhưng tôi đã hy vọng tôi có thể lưu các tệp .properties mới (ngôn ngữ mới) bên cạnh các ngôn ngữ hiện tại (thư mục tài nguyên). Tôi có một lớp tin nhắn tĩnh mà biết làm thế nào để tải các nguồn lực cả từ đĩa và cả hai mặc định trong thư mục tài nguyên. Nhưng nếu người dùng có tệp .jar này trên một số máy khác, anh ta sẽ không có các ngôn ngữ mới vì chúng nằm trên đĩa trên máy tính đó, không phải bên trong tệp .jar.

Trả lời

0

Tài nguyên được tải thông qua trình tải lớp và trình tải lớp mặc định lưu trữ rất nhiều.

Bạn cần trình nạp lớp của riêng mình với hành vi bạn cần, để đọc tài nguyên từ hệ thống tệp không tĩnh.

+0

@ Thorbjørn Ravn Andersen Nếu tôi thử điều này: 'MyClass.class.getClassLoader()' Tôi không thấy bất kỳ phương pháp nào có thể cho tôi một số đường dẫn. – vale4674

+0

Bạn không thể ghi tài nguyên. Tuy nhiên, bạn có thể có trình nạp lớp tải tài nguyên từ một hệ thống tệp. –

0

Sự cố là đường dẫn lớp có thể chứa nhiều thư mục gốc để phân biệt thư mục nào cần lưu trữ sẽ khó mà không có tệp hoặc thư mục hiện có.

Nếu bạn đã tải tệp hiện có.

File existingFile = ...; 
File parentDirectory = existingFile.getParentFile(); 
new File(parentDirectory, "newProperties.properties"); 

Nếu không, hãy thử xử lý trên thư mục bạn biết là duy nhất trong thư mục tài nguyên của bạn. (Không chắc chắn nếu điều này hoạt động)

URL url = this.getClass().getResource("/parentDirectory"); 
File parentDirectory = new File(new URI(url.toString())); 
new File(parentDirectory, "newProperties.properties"); 
+0

@ Lionel Port Tôi đã thử kết hợp này và nó không hoạt động. \t \t 'URL url = FilesUtil.class.getResource ("/messages/messages.properties "); \t \t System.out.println (url); \t \t Tệp tệp = tệp mới (url.toURI()); \t \t System.out.println (tệp); ' Đầu ra đầu tiên cung cấp cho tôi đường dẫn tuyệt đối trên đĩa nhưng khi tôi cố gắng tạo một tệp từ nó, nó mang lại cho tôi một' java.lang.IllegalArgumentException: URI có một thẩm quyền thành phần' ngoại lệ. Có vẻ như java không thể viết bên trong không gian làm việc của nó (tệp .jar). – vale4674

+0

Có nó sẽ chỉ hoạt động nếu các tập tin thuộc tính nằm trong một thư mục mở rộng mà bạn có quyền ghi. Xin lỗi, tôi không nhận ra bạn đang cố cập nhật tệp jar. –

+0

Có thể được đơn giản hóa thành; 'tệp mới (parentDirectoryUrl.getFile())' – Ducaz035

6

Như những người khác đã đề cập, tài nguyên có được thông qua Trình nạp lớp. Có gì hai phản ứng hiện nay đã thất bại trong việc căng thẳng, tuy nhiên, là những điểm sau:

  • classloaders có nghĩa là để trừu tượng quá trình lấy lớp học và các nguồn lực khác. Tài nguyên không phải là tệp trong hệ thống tệp; nó có thể là một URL từ xa, hoặc bất cứ điều gì ở tất cả mà bạn hoặc ai đó khác có thể thực hiện bằng cách mở rộng java.lang.ClassLoader.
  • Trình nạp lớp tồn tại trong chuỗi phân công con/phụ huynh. Hành vi bình thường của ClassLoader là cố gắng lấy tài nguyên từ cha mẹ lần đầu tiên, và sau đó chỉ tìm kiếm tài nguyên của riêng nó — nhưng một số trình nạp lớp làm thứ tự ngược lại (ví dụ, trong các thùng chứa servlet).Trong mọi trường hợp, bạn cần phải xác định vị trí của trình nạp lớp nào để lấy nội dung bạn muốn chèn vào, và thậm chí sau đó một trình nạp lớp khác ở trên hoặc dưới nó có thể "lấy cắp" các yêu cầu tài nguyên của mã máy khách của bạn.
  • Khi Lionel Port chỉ ra, ngay cả một ClassLoader duy nhất có thể có nhiều vị trí mà từ đó nó tải nội dung.
  • Trình nạp lớp được sử dụng để tải các lớp học. Nếu chương trình của bạn có thể ghi các tệp vào một vị trí nơi các lớp được nạp, điều này có thể dễ dàng trở thành một nguy cơ bảo mật, bởi vì người dùng có thể đưa mã vào ứng dụng đang chạy của bạn.

Phiên bản ngắn: không thực hiện. Viết một giao diện trừu tượng hơn cho khái niệm "kho lưu trữ nội dung giống như tài nguyên mà tôi có thể lấy nội dung" và giao diện con cho "kho lưu trữ nội dung giống như tài nguyên mà tôi có thể tải nội dung, nhưng cũng thêm nội dung từ". Thực hiện sau theo cách mà cả hai sử dụng ClassLoader.getContextClassLoader().getResource() (để tìm kiếm đường dẫn lớp) và, nếu không thành công, hãy sử dụng một số cơ chế khác để tải nội dung mà chương trình có thể đã thêm từ một số vị trí.

+0

@ sacundim Tôi đã chỉnh sửa câu hỏi của mình vì nhận xét quá lớn. – vale4674

0

Cắt thư mục dự án chính của các thư mục con biên dịch ("/ target/classes", "mục tiêu/thử nghiệm lớp học") và bạn có đường dẫn cơ bản để tái tạo lại thư mục dự án của bạn với:

import java.io.File; 
import java.io.IOException; 
import java.net.URISyntaxException; 

public class SubfolderCreator { 

public static void main(String... args) throws URISyntaxException, IOException { 
    File newResourceFolder = createResourceSubFolder("newFolder"); 
} 

private static File createResourceSubFolder(String folderName) throws URISyntaxException, IOException { 
    java.net.URL url = SubfolderCreator.class.getResource("/EXISTING_SUBFOLDER/"); 
    File fullPathToSubfolder = new File(url.toURI()).getAbsoluteFile(); 
    String projectFolder = fullPathToSubfolder.getAbsolutePath().split("target")[0]; 
    File testResultsFolder = new File(projectFolder + "src/test/resources/" + folderName); 
    if (!testResultsFolder.exists()) { 
     testResultsFolder.mkdir(); 
    } 
    return testResultsFolder; 
} 
} 
0

Các đoạn mã sau ghi vào thư mục classes cùng với các tệp lớp.

Như những người khác đã lưu ý, hãy cẩn thận khi ghi đè lên các tệp lớp học. Tốt nhất để đưa các tệp mới của bạn vào một thư mục riêng biệt; tuy nhiên, thư mục đó cần phải tồn tại. Để tạo nó, tạo một thư mục con bên trong các tài nguyên trong nguồn, có lẽ chứa một tệp rỗng. Ví dụ: src\main\resources\dir\empty.txt.

public class WriteResource { 
    public static void main(String[] args) throws FileNotFoundException { 
     String thing = "Text to write to the file"; 
     String dir = WriteResource.class.getResource("/").getFile(); 
     //String dir = WriteResource.class.getResource("/dir").getFile(); 
     OutputStream os = new FileOutputStream(dir + "/file.txt"); 
     final PrintStream printStream = new PrintStream(os); 
     printStream.println(thing); 
     printStream.close(); 
    } 
} 

Đây là mẹo, nhưng tôi rất lo lắng về việc triển khai điều này ngoài môi trường được kiểm soát chặt chẽ. Tôi không thực sự thích ý tưởng của những người không được phép viết thư cho thư mục classes của tôi!

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