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.
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.
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.
If you want to create a test.xml file in the directory returned by getResource(), try this:
File file = new File(classLoader.getResource(".").getFile() + "/test.xml");
if (file.createNewFile()) {
System.out.println("File is created!");
} else {
System.out.println("File already exists.");
}
Calling getFile() on a non-existent directory or file will return null, as explained in Reid's answer.
It looks like your call to getResource("file/test.xml") is likely returning null.
I'm curious, what is the full path to your XML file? For this to work, the resources directory needs to be placed in your webapp directory. If you are trying to use the standard Java resources structure (src/main/resources) then that Spring MVC mapping will not work.
EDIT: After seeing your answer to @Ascalonian's comment, this will not work since the file doesn't exist. Like I mentioned earlier, getResource("file/test.xml") will return null so the following call to getFile() will throw the NPE. Maybe you should check if getResource returns null and use that as an indication that the file needs to be created.
The src/main/resources folder is a folder that is supposed to contain resources for your application. As you noted, maven packages these files to the root of your file so that you can access them in your library.
Have a look at the Maven documentation about the standard directory layout.
In certain cases, it is possible to write to the context but it is not a good idea to try it. Depending on how your webapp is deployed, you might not be able to write into the directory. Consider the case when you deploy a .war archive. This would mean that you try to write into the war archive and this won't be possible.
A better idea would be to use a temporary file. In that way you can be sure this will work, regardless of the way your web application is deployed.
Agree with Sandiip Patil. If you didn't have folder inside your resources then path will be /sudoinput.txt or in folder /folder_name/sudoinput.txt. For getting file from resources you should use YourClass.class.getResource("/filename.txt");
For example
Scanner scanner = new Scanner(TestStats.class.getResourceAsStream("/123.txt"));
or
Scanner scanner = new Scanner(new `FileInputStream(TestStats.class.getResource("/123.txt").getPath()));`
Also look at: this
You can output text to a file in the resources folder, but the process is a bit tedious.
- Tell Maven to write the location of your
resourcesfolder into a file - Read the location of your
resourcesfolder in Java - Use that location to write your file to
Notes
Why bother specifying the location of your
resourcesfolder file? Isn't itsrc/main/resourcesalways? Well no, if you have a nested module structure likerootModule ├─ childModule1 │ └─ src │ └─ main │ └─ resources └─ childModule2 └─ ...then the relative path
src/main/resourcesresolves toparentModule/src/main/resourceswhich does not exist.- Once you write the file to the
resourcesfolder, it will not be accessible throughClass.getResource().Class.getResource()provides you with read access to files located in your classpath. The files located in yourresourcesfolder are "copied" to your binary output folder (read classpath) during "compilation". In order to access your newly created resource file with the help ofClass.getResource(), you will have to recompile & restart the application. However, you can still access it by the location you used for writing the file.
Guide
- add
RESOURCE_PATHproperty to the Maven pom, and tell Maven to compile properties found in resource files - add an utility file
src/main/resources/RESOURCE_PATH, which only contains theRESOURCE_PATHproperty - extract the
RESOURCE_PATHproperty from the utility file in Java - rebuild the project if needed (e.g. if file/folder structure changes)
POM
<project>
...
<properties>
<RESOURCE_PATH>${project.basedir}/src/main/resources</RESOURCE_PATH>
</properties>
...
<build>
...
<resources>
<resource>
<directory>${RESOURCE_PATH}</directory>
<filtering>true</filtering>
</resource>
</resources>
....
</build>
...
</project>
Utility file (src/main/resources/RESOURCE_PATH)
${RESOURCE_PATH}
Java
/**
* Reads the relative path to the resource directory from the <code>RESOURCE_PATH</code> file located in
* <code>src/main/resources</code>
* @return the relative path to the <code>resources</code> in the file system, or
* <code>null</code> if there was an error
*/
private static String getResourcePath() {
try {
URI resourcePathFile = System.class.getResource("/RESOURCE_PATH").toURI();
String resourcePath = Files.readAllLines(Paths.get(resourcePathFile)).get(0);
URI rootURI = new File("").toURI();
URI resourceURI = new File(resourcePath).toURI();
URI relativeResourceURI = rootURI.relativize(resourceURI);
return relativeResourceURI.getPath();
} catch (Exception e) {
return null;
}
}
public static void main(String[] args) throws URISyntaxException, IOException {
File file = new File(getResourcePath() + "/abc.txt");
// write something to file here
System.out.println(file.lastModified());
}
I hope that works. Maybe you need maven resources:resources plugin and do mvn generate-resources process-resources
You can override the file but that would only work in IDE, if it would be executed as part of jar it would fail because it is not a file any more( its file inside file)
Better to externalize file and read/overwrite from that location
If you still would like to read this file and overwrite it then you can do something like
Thread.getclassloader().get resource("/");
This will give you path up to your target/classes directory you can navigate to resources from here using double dots
You can't write to files inside your JAR file, because they aren't actually files, they are ZIP entries.
The easiest way to store configuration for a Java application is to use Preferences:
Preferences prefs = Preferences.userNodeForPackage(MyApp.class);
Now all you have to do is use any of the get methods to read, and put methods to write.
There is absolutely no need to write files into your resource folder inside a jar. All you need to have is a smart classloader structure. Either there is a classloader that allows changing jars (how difficult is that to implement?), or you just setup a classpath that contains an empty directory before listing all the involved jars.
As soon as you want to change a resource, just store a file in that directory. When loading the resource next time, it will be searched on the classpath and the first match is returned - in that case your changed file.
Now it could be that your application needs to be started with that modified classpath, and on top of that it needs to be aware which directory was placed first. You could still setup that classloader structure within a launcher application, which then transfers control to the real application loaded via the newly defined classloader.
For input, try below:
InputStreamReader isReader =
new InputStreamReader(
this.getClass().getResourceAsStream(templateName));
BufferedReader br = new BufferedReader(isReader);
or
InputStreamReader isReader =
new InputStreamReader(
<youclassName>.class.getResourceAsStream(templateName));
BufferedReader br = new BufferedReader(isReader);
For output, try below:
PrintWriter writer =
new PrintWriter(
new File(this.getClass().getResource(templateName).getPath()));
All solution above show how you can receive access to your resources in build folder. It means that resources have been moved to build directory with .class files.
If you need to write some files into resources for saving them after terminated program, then you will have to describe path starting with root project:
./src/main/resources/foo.ext
This solving generally not recommended but may be necessary in other cases.