Create file in resources/source folder in java programmatically?

雨燕双飞 提交于 2019-12-04 00:01:58

As other people have mentioned, resources are obtained through a ClassLoader. What the two current responses have failed to stress, however, is these points:

  • ClassLoaders are meant to abstract the process of obtaining classes and other resources. A resource does not have to be a file in a filesystem; it can be a remote URL, or anything at all that you or somebody else might implement by extending java.lang.ClassLoader.
  • ClassLoaders exist in a child/parent delegation chain. The normal behavior for a ClassLoader is to first attempt to obtain the resource from the parent, and only then search its own resources—but some classloaders do the opposite order (e.g., in servlet containers). In any case, you'd need to identify which classloader's place for getting stuff you'd want to put stuff into, and even then another classloader above or below it might "steal" your client code's resource requests.
  • As Lionel Port points out, even a single ClassLoader may have multiple locations from which it loads stuff.
  • ClassLoaders are used to, well, load classes. If your program can write files to a location where classes are loaded from, this can easily become a security risk, because it might be possible for a user to inject code into your running application.

Short version: don't do it. Write a more abstract interface for the concept of "repository of resource-like stuff that I can get stuff from," and subinterface for "repository of resource-like stuff that I can get stuff from, but also add stuff from." Implement the latter in a way that both uses ClassLoader.getContextClassLoader().getResource() (to search the classpath) and, if that fails, uses some other mechanism to get stuff that the program may have added from some location.

RohitKumar

Java 8 Solution

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

This will surely create new folder in resource folder. but you will find new folder in your target runtime.

which will be ProjectName/target/test-classes/newFolder. if you are running this code in test case. Other wise it would be in target/classes

Don't try to find new folder in your src/resources. it will be surely in target/test-classes or target/classes.

Cut the main project folder of the compiled subfolders ("/target/classes", "target/test-classes") and you have the basic path to reconstruct your project folders with:

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

Resources are loaded through a class loader, and the default class loader caches heavily.

You need your own class loader with the behaviour you need, to read resources from a non-static file system.

Problem would be the classpath can contain multiple root directories so distinguishing which one to store would be hard without an existing file or directory.

If you have an existing file loaded.

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

Otherwise try an get a handle on a directory you know is unique in your resources directory. (Not sure if this works)

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

The following code writes into the classes directory, along with the class files.

As others have noted, beware of overwriting class files. Best to put your new files into a separate directory; however, that directory needs to already exist. To create it, create a sub-directory within the resources in the source, perhaps containing an empty file. For example 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();
    }
}

This does the trick, but I'd be nervous about deploying this outside of a strictly controlled environment. I don't really like the idea of unauthorised persons writing to my classes directory!

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!