以编程方式在 java 的资源/源文件夹中创建文件



我有两个资源文件夹。

SRC - 这是我的.java文件

资源 - 这是我的资源文件(图像,.属性(组织在文件夹(包(中。

有没有办法以编程方式在该资源文件夹中添加另一个 .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

.

正如其他人所提到的,资源是通过类加载器获得的。 然而,目前的两种回应未能强调的是以下几点:

  • 加载器旨在抽象获取类和其他资源的过程。 资源不必是文件系统中的文件;它可以是远程 URL,也可以是您或其他人可能通过扩展 java.lang.ClassLoader 来实现的任何内容。
  • 类加载器存在于子/父委托链中。 类加载器的正常行为是首先尝试从父级获取资源,然后才搜索自己的资源,但某些类加载器执行相反的顺序(例如,在 servlet 容器中(。 在任何情况下,您都需要确定哪个类加载器的位置来获取您想要放入内容的内容,即使这样,它上方或下方的另一个类加载器也可能"窃取"客户端代码的资源请求。
  • 正如Lionel Port指出的那样,即使是单个ClassLoader也可能有多个位置来加载内容。
  • 类加载
  • 器习惯于加载类。 如果程序可以将文件写入加载类的位置,则很容易成为安全风险,因为用户可能会将代码注入正在运行的应用程序。

简短版本:不要这样做。 为"我可以从中获取内容的类资源存储库"的概念编写一个更抽象的接口,并为"我可以从中获取内容,但也从中添加内容的类资源存储库"编写子接口。 以既使用 ClassLoader.getContextClassLoader().getResource()(搜索类路径(的方式实现后者,如果失败,则使用其他机制来获取程序可能从某个位置添加的内容。

问题是类路径可以包含多个根目录,因此如果没有现有的文件或目录,区分要存储哪个根目录将很困难。

如果加载了现有文件。

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");

剪切已编译子文件夹的主项目文件夹("/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目录。

正如其他人所指出的,当心覆盖类文件。 最好将新文件放入单独的目录中;但是,该目录需要已存在。 若要创建它,请在源中的资源中创建一个子目录,可能包含空文件。 例如srcmainresourcesdirempty.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????IdeaProjectsback-endtargetclassesapplication.properties的文件

相关内容

最新更新