簡體   English   中英

以編程方式在java中的資源/源文件夾中創建文件?

[英]Create file in resources/source folder in java programmatically?

我有兩個資源文件夾。

src - 這是我的 .java 文件

資源 - 這是我在文件夾(包)中組織的資源文件(圖像、.properties)。

有沒有辦法以編程方式在該資源文件夾中添加另一個 .properties 文件?

我試過這樣的事情:

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

在創建之前:

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

但它會在文件系統上查找該路徑。 如何強制它查看資源文件夾?

編輯:讓我說它是關於什么的。 我有一個 GUI 應用程序,我支持 2 種語言(資源文件夾中的 2 個 .properties 文件)。 現在我添加了一個選項,用戶可以輕松翻譯應用程序,當他完成時,我將新的 .properties 保存在某個隱藏文件夾中的磁盤上並從那里讀取。 但我希望我可以將新的 .properties 文件(新語言)保存在當前語言(資源文件夾)旁邊。 我有一個靜態 Messages 類,它知道如何從磁盤和資源文件夾中的默認資源加載資源。 但是如果用戶在其他機器上使用這個 .jar 文件,他就不會擁有那些新語言,因為它們在該計算機的磁盤上,而不是在 .jar 文件中。

Java 8 解決方案

 Path source = Paths.get(this.getClass().getResource("/").getPath());
        Path newFolder = Paths.get(source.toAbsolutePath() + "/newFolder/");
        Files.createDirectories(newFolder);

這肯定會在資源文件夾中創建新文件夾。 但是您會在目標運行時中找到新文件夾。

這將是ProjectName/target/test-classes/newFolder 如果您在測試用例中運行此代碼。 否則,它將在target/classes

不要嘗試在src/resources查找新文件夾。 它肯定會在target/test-classestarget/classes

正如其他人提到的,資源是通過 ClassLoader 獲取的。 然而,目前的兩種回應都沒有強調以下幾點:

  • 類加載器旨在抽象獲取類和其他資源的過程。 資源不必是文件系統中的文件; 它可以是遠程 URL,也可以是您或其他人通過擴展java.lang.ClassLoader可能實現的任何內容。
  • 類加載器存在於子/父委托鏈中。 ClassLoader 的正常行為是首先嘗試從父級獲取資源,然后才搜索它自己的資源——但有些類加載器的順序相反(例如,在 servlet 容器中)。 在任何情況下,您都需要確定哪個類加載器的位置來獲取您想要放入的東西,即使它上面或下面的另一個類加載器也可能“竊取”您的客戶端代碼的資源請求。
  • 正如 Lionel Port 指出的那樣,即使是單個 ClassLoader 也可能有多個位置來加載內​​容。
  • 類加載器用於加載類。 如果您的程序可以將文件寫入加載類的位置,則這很容易成為安全風險,因為用戶可能會將代碼注入您正在運行的應用程序中。

簡短版本:不要這樣做。 為“我可以從中獲取東西的類似資源的存儲庫”的概念編寫一個更抽象的接口,並為“我可以從中獲取和添加東西的類似資源的存儲庫”編寫子接口。 以既使用ClassLoader.getContextClassLoader().getResource() (搜索類路徑)的方式實現后者,如果失敗,則使用其他機制來獲取程序可能從某個位置添加的內容。

剪切已編譯子文件夾(“/target/classes”、“target/test-classes”)的主項目文件夾,您就有了重建項目文件夾的基本路徑:

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

以下代碼與類文件一起寫入classes目錄。

正如其他人所指出的,小心覆蓋類文件。 最好把你的新文件放到一個單獨的目錄中; 但是,該目錄需要已經存在。 要創建它,請在源中的資源中創建一個子目錄,其中可能包含一個空文件。 例如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();
    }
}

這可以解決問題,但我會擔心在嚴格控制的環境之外部署它。 我真的不喜歡未經授權的人寫入我的classes目錄的想法!

根據以下代碼,您可以獲取或創建一個文件並將其用作 util 方法。

public static File getFileFromResource(String filePath) {
    ClassLoader classloader = Thread.currentThread().getContextClassLoader();
    return new File(Objects.requireNonNull(classloader.getResource(filePath)).getFile());
}

項目結構

您應該指定文件或文件夾的相對路徑。 用法:

getFileFromResource("application.properties");

輸出:文件路徑為C:\\Users\\????\\IdeaProjects\\back-end\\target\\classes\\application.properties

資源通過類加載器加載,默認的類加載器緩存。

您需要自己的類加載器以及您需要的行為,以從非靜態文件系統中讀取資源。

問題是類路徑可以包含多個根目錄,因此在沒有現有文件或目錄的情況下很難區分要存儲哪個。

如果您加載了現有文件。

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

否則,嘗試獲取您知道在您的資源目錄中唯一的目錄的句柄。 (不確定這是否有效)

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM