Using file from within JAR, while runnig app from jar - java

I am trying to use file, when running application as JAR.
When I run application through Intelij, everything is fine. However when I try to run it via jar, I cannot access the file.
I tried to read few topics containing similar matter, but non of them help
(like Reading a resource file from within jar or How do I read a resource file from a Java jar file?
)
Here is my target tree, and resources:
When I use
String path = String
.join("", "classpath:static\assets\config\", fileName);
File file = ResourceUtils.getFile(path);
InputStream targetStream = new FileInputStream(file)
During intelij run, everything works.
In the case of jar, I tried:
String path = String
.join("", "static\assets\config\", fileName).replace("\\","/")).toExternalForm();
String path2 = String
.join("", "static\assets\config\", fileName).replace("\\","/")).getFile();
String path3 = String
.join("", "static\assets\config\", fileName).replace("\\","/")).getPath();
and many other. They result in correct path, for example:
file:/D:/Projects/myProject/target/classes/static/assets/config/fileName (in case of toExternalForm)
/D:/Projects/myProject/target/classes/static/assets/config/fileName (in case of getFile)
However all of them results in null InputStream, when I try:
InputStream in = getClass().getResourceAsStream(everyPath);
I get an error:
java.io.FileNotFoundException: D:\Projects\myProject\target\project-app-1.0.jar\BOOT-INF\classes\static\assets\config\fileName (The system cannot find the path specified)
When the path in the project-app-1.0.jar when I open it by 7zip is exactly:
D:\Projects\myProject\target\project-app-1.0.jar\BOOT-INF\classes\static\assets\config\fileName
This is how my resource handler looks like:
private static final String[] CLASSPATH_RESOURCE_LOCATIONS = {
"classpath:/resources/", "classpath:/static/"};
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/**").addResourceLocations(
CLASSPATH_RESOURCE_LOCATIONS);
}

forget about "files" when you want to use something inside your jar, its just a simple "Resource" that your have to use with getResource.
If you use a standard packaging system, everything inside "resources" folder are put at the root of your JAR, so if you want to read your "foo.txt" file inside "static\assets\config\" folder you have to do use method:
InputStream in = ClassLoader.getSystemResourceAsStream("static/assets/config/foo.txt");

Related

store file in spring boot resource folder after deployment

I have deployed a spring-boot application JAR file. Now, I want to upload the image from android and store it in the myfolder of resource directory. But unable to get the path of resource directory.
Error is:
java.io.FileNotFoundException: src/main/resources/static/myfolder/myimage.png
(No such file or directory)
This is the code for storing the file in the resource folder
private final String RESOURCE_PATH = "src/main/resources";
String filepath = "/myfolder/";
public String saveFile(byte[] bytes, String filepath, String filename) throws MalformedURLException, IOException {
File file = new File(RESOURCE_PATH + filepath + filename);
OutputStream out = new FileOutputStream(file);
try {
out.write(bytes);
} catch (Exception e) {
e.printStackTrace();
} finally {
out.close();
}
return file.getName();
}
UPDATED:
This is what I have tried
private final String RESOURCE_PATH = "config/";
controller class:
String filepath = "myfolder/";
String filename = "newfile.png"
public String saveFile(byte[] bytes, String filepath, String filename) throws MalformedURLException, IOException {
//reading old file
System.out.println(Files.readAllBytes(Paths.get("config","myfolder","oldfile.png"))); //gives noSuchFileException
//writing new file
File file = new File(RESOURCE_PATH + filepath + filename);
OutputStream out = new FileOutputStream(file); //FileNotFoundException
try {
out.write(bytes);
} catch (Exception e) {
e.printStackTrace();
} finally {
out.close();
}
return file.getName();
}
Project structure:
+springdemo-0.0.1-application.zip
+config
+myfolder
-oldfile.png
-application.properties
+lib
+springdemo-0.0.1.jar
+start.sh
-springdemo-0.0.1.jar //running this jar file
Usually when you deploy an application (or start it using Java), you start a JAR file. You don't have a resource folder. You can have one and access it, too, but it certainly won't be src/main/resources.
When you build your final artifact (your application), it creates a JAR (or EAR or WAR) file and your resources, which you had in your src/main/resources-folder, are copied over to the output directory and included in the final artifact. That folder simply does not exist when the application is run (assuming you are trying to run it standalone).
During the build process target/ is created and contains the classes, resources, test-resources and the likes (assuming you are building with Maven; it is a little different if you build using Gradle or Ant or by hand).
What you can do is create a folder e.g. docs next to your final artifact, give it the appropriate permissions (chmod/chown) and have your application output files into that folder. This folder is then expected to exist on the target machine running your artifact, too, so if it doesn't, it would mean the folder does not exist or the application lacks the proper permissions to read from / write to that folder.
If you need more details, don't hesitate to ask.
Update:
To access a resource, which is bundled and hence inside your artifact (e.g. final.jar), you should be able to retrieve it by using e.g. the following:
testText = new String(ControllerClass.class.getResourceAsStream("/test.txt").readAllBytes());
This is assuming your test.txt file is right under src/main/resources and was bundled to be directly in the root of your JAR-file (or target folder where your application is run from). ControllerClass is the controller, which is accessing the file. readAllBytes just does exactly this: read all the bytes from a text file. For accessing images inside your artifact, you might want to use ImageIO.
IF you however want to access an external file, which is not bundled and hence not inside your artifact, you may use File image = new File(...) where ... would be something like "docs/image.png". This would require you to create a folder called docs next to your JAR-artifact and put a file image.png inside of it.
You of course also may work with streams and there are various helpful libraries for working with input- and output streams.
The following was meant for AWT, but it works in case you really want to access the bytes of your image: ImageIO. In a controller you usually wouldn't want to do that, but rather have your users access (and thus download) it from a given available folder.
I hope this helps :).

Java - How to get the correct absolute path of a file within a project

I have an XML file in a folder within my Java project, and I'd like to get its absolute path, so I can load it as a File in order to parse it(DOM). Instead of using an absolute/relative path, I want to specify only the file name, and get the absolute path after that. I tried to do this in a few different ways, but there is always a folder name missing from the path I get.
I get:
C:\Users\user\workspace\projectName\Input.xml<br>
instead of:
C:\Users\user\workspace\projectName\\**Folder1**\\Input.xml
-
File input = new File(project.getFile("Input.xml").getLocation().toString());`
File input = new File(project.getFile("Input.xml").getRawLocation().makeAbsolute().toString());
File input = new File(project.getFile("Input.xml").getLocationURI().getRawPath().toString());
File input = new File(project.getFile("Input.xml").getFullPath().toFile().getAbsolutePath());
How can I get the correct path, that includes that Folder1?
Reading your question (your project are in workspace directory) I suppose you're talking of a project in Eclipse.
Well the default directory where your app run into Eclipse is right the base dir of your project.
So if you run something like this in your main:
Files.newDirectoryStream(Paths.get("."))
.forEach(path -> {
System.out.println(path);
System.out.println(path.toFile().getAbsolutePath());
});
You should see all the files and directory that are in your project.
So if what you want is just the absolute path to your project run:
System.out.println(Paths.get(".").toFile().getAbsolutePath());
If you want open the resource Input.xml specifying only the name, I suggest to move all the files you need in a directory and run a method like this:
public static File getFileByName(String name, String path) throws IOException {
ArrayList<File> files = new ArrayList<>();
Files.newDirectoryStream(Paths.get(path))
.forEach(p -> {
if (p.getFileName()
.equals(name))
files.add(p.toFile());
});
return files.size() > 0 ? files.get(0) : null;
}

Jar null point exception when reading a file

The following code works fine on my Eclipse IDE.
private void getLayersAndDisplay() throws Exception {
URL imageURL = ImageLab.class.getResource("earthlights.jpg");
File imageFile = new File(imageURL.toURI());
URL shapeFileURL = ImageLab.class.getResource("countries.shp");
File shapeFile = new File(shapeFileURL.toURI());
URL shapeFileURL2 = ImageLab.class.getResource("Brasil.shp");
File shapeFile2 = new File(shapeFileURL2.toURI());
displayLayers(imageFile, shapeFile,shapeFile2);
}
However, when compiling to a jar, it gives me a null pointer exception. I thought that since I am getting it as a class.getResource, it would work. Can't I use the File class in a jar? Not even in a cast?
Thank you
An entry of a zip file (that's what a jar file is) is not a file existing in your file system. So you can't use a File, which represents a path on your filesystem, to refer to a zip entry. And you can't use file IO to read its content, since it's not a file.
I have no idea what you want to do, but if you want to read the content of the jar resource, just use ImageLab.class.getResourceAsStream() to get an InputStream back, reading from the entry.

Absolute Path from File in Package

Let's say I have a package: com.example.resources and inside it I have picture.jpg and text.txt - How can I use only the package path to identify the absolute filepath of picture.jpg and text.txt?
Is this correct?
File file1 = new File("/com/example/resources/picture.jpg");
file1.getAbsolutePath();
File file2 = new File("/com/example/resources/text.txt");
file2.getAbsolutePath();
"I'm trying to reference those files within the application so that when I deploy the application to different systems I won't have to reconfigure the location of each resource "
You don't want to use a File, which will load from the file system of the local machine, you want to load through the class path, as that's how embedded resources should be read. Use getClass().getResourceAsStream(..) for the text file and getClass().getReource(..) for the image
Your current path you're referencing looks like it should work, given the package name you've provided.
Take a look at this answer and this answer as some references.
I've figured out how to do it. Here is the code that I used:
public String packagePathToAbsolutePath(String packageName, String filename) {
String absolutePath = "File not found";
URL root = Thread.currentThread().getContextClassLoader().getResource(packageName.replace(".", "/"));
File[] files = new File(root.getFile()).listFiles();
for (File file : files) {
if (file.getName().equals(filename)) {
absolutePath = file.getName();
return absolutePath;
}
}
return absolutePath;
}
This method was really useful because it allowed me to configure the resource paths within the application so that when I ran the application on different systems I didn't have to reconfigure any paths.

load a folder from a jar

I am trying to access a directory inside my jar file. I want to go through every of the files inside the directory itself. I tried using the following:
File[] files = new File("ressources").listFiles();
for (File file : files) {
XMLParser parser = new XMLParser(file.getAbsolutePath());
// some work
}
If I test this, it works well. But once I put the contents into the jar, it doesn't because of several reasons. If I use this code, the URL always points outside the jar.
structure of my project :
src
controllers
models
class that containt traitement
views
ressources
See this:
How do I list the files inside a JAR file?
Basically, you just use a ZipInputStream to find a list of files (a .jar is the same as a .zip)
Once you know the names of the files, you can use getClass().getResource(String path) to get the URL to the file.
I presume this jar is on your classpath.
You can list all the files in a directory using the ClassLoader.
First you can get a list of the file names then you can get URLs from the ClassLoader for individual files:
public static void main(String[] args) throws Exception {
final String base = "/path/to/folder/inside/jar";
final List<URL> urls = new LinkedList<>();
try (final Scanner s = new Scanner(MyClass.class.getResourceAsStream(base))) {
while (s.hasNext()) {
urls.add(MyClass.class.getResource(base + "/" + s.nextLine()));
}
}
System.out.println(urls);
}
You can do whatever you want with the URL - either read and InputStream into memory or copy the InputStream into a File on your hard disc.
Note that this definitely works with the URLClassLoader which is the default, if you are using an applet or a custom ClassLoader then this approach may not work.
NB:
You have a typo - its resources not ressources.
You should use reverse domain name notation for your project, this is the convention.

Categories

Resources