how to create file in java in resources directory - java

I have a maven project and need to write JSON objects in file.json that should be located in
src/main/resources/
But before I need to check if file exists. If not than create it.
public static void writeMenuJSon(String jsonParamIn) {
JsonParser parser = new JsonParser();
JsonObject modulJson = parser.parse(jsonParamIn).getAsJsonObject();
//TODO check if file exists and create file if not
code here ...
// write to file JSON object
try (Writer writer = new FileWriter("path to file")){
Gson gson = new GsonBuilder().create();
gson.toJson(modulJson, writer);
} catch (IOException e) {
e.printStackTrace();
}
}

Something is totally wrong if you are creating dynamically file in src/main/resources This is only going to work in your development environment. When you deploy your code using Jar or War there won't be this directory on file system. It will be contained within Jar / War or other packaging.
If you understand above and still want to do it. Go related to your current working directory to create file, Usually the working directory when you launch your Main from IDE is setup to root of project so create a file at
src/main/resources/foo.txt
will do it. Alternatively you can figure out your current working directory from your IDE launcher or at runtime using
System.getProperty("user.dir");

What are you exactly trying to achieve writing the JSON file to the mentioned directory ?
I might miss something important in your question but:
it is possible to create code that does this thing but i'm not sure at all how are you going to run this code and is it sane solution to your problem?
When you mvn package the project name P having this "src/main/resources/" resources there will be added to package P.war/.jar or so but there will not be any JSON-file in directory until you run the code - this code you are after - that generates it and it is not done without some -maybe ugly- extra job.
If you have this code included in this project it will be run only when the project package is run. And there will not be this "src/main/resources/" where to write it.

Related

How to create correct resource file path in a java jar file

Sitting here with a bigger java project (for a first year software student) having some troubles creating the correct file path to resources.
I right now have files in the form of .txt, .png, .jpg, and a .gif.
Right now i use paths like this to find a text file:
File userFile = new File("Source Code/files/users.txt");
Or paths like this to create an image loaded in my FX code:
File logoPath = new File("Source code/files/graphics/Streamy_logo.png");
Image logoImage = new Image(logoPath.toURI().toString());
logo.setImage(logoImage);
This works fine in my IDE (IntelliJ), however it doesn't work when i create the project as a Jar file.
I think is has to do with the "source code" directory not created in the jar-file, which makes sense now.
Tried to read different subjects, but it seems a bit different if i should use a getResources-method, set a resourceStream or something else.
Can anybody please help me with this.
Thank you!
You can't load files like that in .jar files here's an example on how to read BufferedImages.
But first, make sure you have marked the resource folder as a resource folder in IntelliJ by right-clicking the folder in the project view and going down to "Mark directory as" and checking resource root.
BufferedImage exampleBlock = null;
try {
exampleBlock = ImageIO.read(ClassLoader.getSystemResource("exampleBlock.png"));
} catch (IOException e) {
e.printStackTrace();
}
By using this method of getting files all your files will be implemented into the .jar file and you can use them by calling their file name + extension
For maven or gradle projects, that respects maven directories convention you can simply use
getClass().getResource("/your_file_located_in_src_main_resources.extension").getPath()

Illegal Argument Exception: URI is not hierarchical with runable .jar file

I know this question has been asked a bunch of times before, but I'm peeled through all the other threads and tried a bunch of stuff, but can't find anything that resolves my issue. I have a program that compiles and runs without issue in Eclipse, but when I export a runnable .jar file, it won't launch. I tried running it from the cmd prompt, and got the error Illegal Argument Exception: URI in not hierarchical. This is happening in an included sound file which I have as a classpath resource. The code is like this:
try {
pop = new File(IntroView.class.getResource("/model/pop.wav")
.toURI());
} catch (URISyntaxException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
From what I've read it's a problem with the way that the file is being packed up into the .jar, but I'm having a hard time wrapping my head around it. Can anybody shed some light on this and possibly provide a solution? Thanks.
I am sorry but it seems you cannot represent a File object from inside a JAR. When locating a file using File object it checks for file in the OS directory structure only. The File object can locate the JAR itself in a directory but not what's inside.
You can get the InputStream to the file inside JAR like this as stated in a few places:
InputStream input = PlaySound.class.getResourceAsStream("Kalimba.mp3");
You could have these options:
Read the file from JAR and write it outside in your directory and
then get the File Object.
Extract the JAR to a folder and point to that with a File.
Simply get the InputStream and play the file as shown here:
How can I play sound in Java?
Alright so I got it working, but it's not really an ideal solution. What I ended up doing is creating a folder within the project, but outside of the source. So before, the resources were in
Project/src/Model/pop.wav
Now they are in
Project/Resources/pop.wav
I then just accessed then like this
pop = new File("Resources/pop.wav");
So as this stands, it still only works when launching from the IDE, but what I did was add a new folder within the same folder that the .jar is being run from which contained all the same resource files. The file reference looks for pop.wav relative to whichever directory the program(either in the IDE of from the .jar) is being run from, so it finds the files in this new folder and works fine. I don't feel it's the prettiest solution, but it works anyway.

How to create a folder in eclipse for storing serialized objects?

I want to serialize some objects in my Java code. I don't want to put it in some random folder on the hard drive. I want it to be inside A FOLDER in my eclipse project folder. How do I make this folder and store my objects in it ?
Is this a good practice ? Will there be a problem if I try to make a self-contained JAR out of this project ?
Below source code shows how to create subfolder in current directory:
import java.io.File;
public class SourceCodeProgram {
public static void main(String argv[]) throws Exception {
File currentFolder = new File(".");
File workingFolder = new File(currentFolder, "serialized");
if (!workingFolder.exists()) {
workingFolder.mkdir();
}
System.out.println(workingFolder.getAbsolutePath());
}
}
When you run this source code and refresh Eclipse project you should see serialized directory in Eclipse project structure. Now you can use it and store all files in it.
In my app, when I want to store some data in hard drive, I always use user recommendation. I create application.properties file which contains key:
working.folder=/example/app-name
App reads this file at the start and creates this folder if it needs it. Second solution can be "app parameter". When I need only one or two parameters from users I read it from command line. For example user run my app using that command:
java -jar app.jar -dir /example/app-name
When user do not provide any folder I use default folder - current directory.
helpful links:
How to get Current Directory through File.
Getting the Current Working Directory in Java.
List item.
args4j.
Reading Properties file in Java
It depends what information those serializable objects have.
Also if you want to have a folder inside your codebase (but deployed as a folder only), you can write code, to write or read files:
URL dir_url = ClassLoader.getSystemResource(dir_path);
// Turn the resource into a File object
File dir = new File(dir_url.toURI());
// List the directory
String files = dir.list()
Note directory should be in classpath.
Steps:
Right click your project's folder in the Package Explorer
Locate the "New" menu item and hover it
Locate "Folder" in the opened menu and click it
Give your folder a name
Click the "Finish" button at the bottom
This will create a folder that should be accessible from your working directory when running from within eclipse.
It is a bad idea to fiddle with files that are within the JAR file during runtime. Imagine a scenario when there are two or more JVMs running the same JAR, this will also mean they work with the same files and reading/writing to those files may cause collisions. You would generally want to separate those files from each other.
So unless those files are read-only, you should not include them in your JAR (otherwise it is fine)
Aren't you better off writing to the user directory, e.g. in a subfolder like .myApp/?
You would do something like this to set up/initialize the directory:
File userDir = new File(System.getProperty("user.home"));
File storageDir = new File(userDir, ".myApp");
if (!storageDir.exists())
storageDir.mkdir();
// store your file in storageDir
Have a look here to find out where userDir is usually located (though you don't necessarily need to care).
If you launch your program in Eclipse, then by default the current working directory of the process will be the project's root directory. Then you can initialize and use a directory named serialized in your project's root like this:
File serializedDir = new File("serialized");
if (!serializedDir.exists()) {
serializedDir.mkdir();
}
Relative paths in your code will be relative the working directory, which is the project's root by default. You can change the default working directory in the launcher configuration.
It depends on your project whether this is a good solution or not. If you don't want/need to share the serialized objects with others then I see nothing wrong with this.
When using the Export function of Eclipse to create a jar from the project, keep in mind that the folder will be selected by default. You have to explicitly deselect it to exclude from the jar. (In any case, it's better to use Maven or Ant for generating jars instead of Eclipse, which you only have to configure once, so no need to worry of the directory getting included by accident.)
You probably also want to exclude the directory from version control.
In order to do this you need two things:
A) Access/Create the specific folder
B) Actually serialize your objects and save them to disk.
For A) this is certainly answered by the other answers here which show how to:
1) Check if folder exists.
2) Create the folder if it does not exist.
Additionally, projects launched in eclipse have as the working directory the eclipse project folder.
For B) you need to serialize your objects using the FileOutputStream .
See http://www.tutorialspoint.com/java/java_serialization.htm .
You can either serialize each object into a separate file, or create one class with an ArrayList (or some other data structure) that contains references to all the objects.
Below a sample Class doing just what you asked using Static Methods as I didn't want to have to instantiate an object. Also, you need to press F5 in your eclipse project to refresh the package explorer and view the new folder and files.
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.util.ArrayList;
public class CreateDirAndSerialize {
public static void main(String args[])
{
ArrayList<String> sampleString = new ArrayList<String> ();
sampleString.add("Test1");
sampleString.add("Test2");
sampleString.add("Test2");
//Get the directory
File directory = getSerializedDirectory();
writeObjects(directory, sampleString);
}
public static void writeObjects(File directory, Object object)
{
try
{
FileOutputStream fileOut =
new FileOutputStream(directory+"//serializedData");
ObjectOutputStream out =
new ObjectOutputStream(fileOut);
out.writeObject(object);
out.close();
fileOut.close();
}catch(IOException i)
{
i.printStackTrace();
}
}
public static File getSerializedDirectory()
{
File serializedDir = new File("serialized");
if (!serializedDir.exists()) {
serializedDir.mkdir();
}
return serializedDir;
}
}
As the question referred to projects within eclipse, the above is for code within an eclipse project. If you want to interact with Eclipse itself, we are talking about eclipse plugin development which is another story entirely so you need to specify that.
Finally, you can also create a custom class holding any variables you want and instantiate a singleton object for containing all your other objects. There are however some limitations when serializing objects, e.g. :
- Object references with static modifier are not serializable.
See this for some rules/tips for some serializable: http://www.xyzws.com/Javafaq/what-are-rules-of-serialization-in-java/208
You can ignore Eclipse and create the directory (and files in it) programmatically, or manually.
Then, refresh your project explorer view in Eclipse, and voila, the directory and files are part of the view.

File path is working in NetBeans but not in built JAR file

I have a file holding default information that I use to load the textFields of my application. I looked up how to get this built into my jar file when I build and I was told to put it in the source packages and it would be brought along, so I have done that.
File Structure:
Project
-Source Packages
-src
~Java Classes
-defaultFiles
~Defaults.txt
The code I am trying to use is this:
BufferedReader in;
try {
URL resourceURL = FuelProperties.class.getResource("/defaultFiles/Defaults.txt");
in = new BufferedReader(new FileReader(resourceURL.getPath()));
}
And this works perfectly when I run it through NetBeans but when I build the project and try to run it from the jar file it is not grabbing the file.
I have verified that the default file is being built and exists in the same file structure shown above.
If you can help me out with this I would be extremely grateful as I have no idea what is keeping this from working. Thanks.
You have to lookup in the classpath, not on the disk.
The API to use is :
URL resourceURL : this.getClass().getResource("relative path in the classpath");
Once you have the url you can open a stream, etc.
EDIT : in the main method, you of course need to replace
this.getClass()
by
ClassName.class
I found the answer after searching through a couple dozen questions. It turns out that you can only get a InputStream of the data within a file within your JAR not a File object like I was attempting to do.
(If you want the File object you just have to extract the files from the JAR in your program and then you have access to it.)
So the code that got my problem to work was simply replacing this:
URL resourceURL = FuelProperties.class.getResource("/defaultFiles/Defaults.txt");
in = new BufferedReader(new FileReader(resourceURL.getPath()));
With this:
in = new BufferedReader(new InputStreamReader(this.getClass().getResourceAsStream("/defaultFiles/Defaults.txt")));
And now it is working both inside NetBeans and in the Built JAR file.

files no longer readable

I have a Java project which has this file structure (shown in Eclipse):
ProjectName
+- Deployment Descriptor: ProjectName
¦- Java Resources:src
¦- Package1
-MyClass.java
¦- FileFolder
-MyFile.txt
And so far from myClass I'm able to read MyFile.txt using:
try
{
reader = new BufferedReader(new FileReader(new File("FileFolder/MyFile.txt")));
while((line=reader.readLine())!=null)
{
line=line.trim();
myVector.add(line);
}
reader.close();
}
catch(Exception e)
{
e.printStackTrace();
}
But when I put Package1 into a Dynamic Web Project AND the FileFolder folder in root, the file is no longer found.
Does anyone know how to read the file?
Thanks in advance!
Dynamic Web Projects generate WAR files.
The server may or may not expand the WAR file back to a file system structure.
You're best off using the Class or ClassLoader .getResourceAsStream("/FileFolder/MyFile.txt") which can read files from JAR/WAR files, and returns an InputStream.
Example:
reader = new BufferedReader(new InputStreamReader(this.getClass().getResourceAsStream("/FileFolder/MyFile.txt")));
Edit: If this is from a Servlet, consider using gawi's answer instead.
Edit 2: If this is in a static method, you'll need to use MyClass.class instead of this.getClass(), where MyClass is the class name.
You are opening a file using a path relative to the current working directory. That's not likely to work on a web app container because the current working directory will not be the root of your application.
Furthermore, you file might not be on the file system but rather in a WAR file.
The proper way to open a file in a webapp is to use the ServletContext.getResourceAsStream() method.

Categories