Exported Jar file won't read file inside jar - java

In the code sample below, when I test the code in Eclipse it works just fine. However, when I export the jar file and test it via the command line, it throws an error: IIOException: Can't read input file!
private BufferedImage img = null;
private String imgSource;
if (img == null)
{
try {
URL url = getClass().getResource("Images/questionMark.png");
System.out.println(url.getPath());
/* This prints: file:/C:/Users/Keno/Documents/javaFile.jar!/javaFile/Images/questionMark.png */
File file = new File(url.getPath());
img = ImageIO.read(file);
imgSource = file.getName();
} catch (IOException e) {
e.printStackTrace();
}
}
The file I want to get is located inside the Images folder which is inside the javaFile package. I've noticed one thing that may indicate the problem.
In the print statement I have, I notice an exclamation sign at the end of the javaFile.jar section. Is that correct? Could that indicate an issue with the file or structure?
Also, just in case someone has a better suggestion as to how I should load the file, I'll tell you my intentions. I would like to load the file from a relative location (Images folder) in the jar. I would like to display it (Already done in my actual code) and also store the location to be passed later on to another function (also done).

try this
public void test() {
try(InputStream is = getClass().getResourceAsStream("Images/questionMark.png")) {
ImageIO.read(is);
} catch (IOException e) {
e.printStackTrace();
}
}

You should try to check if your class is in the same directory than Images inside your jar.
|
|- Your class
|- Images
|- questionMark.png
Also, have you tried using directly your url object ?
File file = new File(url);

Related

Java: Read image from current src directory

I would like to load an image from my current src directory where the java class files are located as well. However, I always get an IOException..
And how can I make sure the file gets loaded properly on Mac/Linux as well on Windows?
My code so far:
String dir = System.getProperty("user.dir") + "/Logo_transparent.png";
File imageFile = new File(dir);
BufferedImage bufferedImage = null;
try {
bufferedImage = ImageIO.read(imageFile);
} catch (IOException e) {
System.out.println(e.getMessage());
System.out.println(dir);
System.out.println();
}
IOException message:
Can't read input file!
(My path is correct - is it because of the space between Google and Drive?)
/Users/myMac/Google Drive/Privat/Programming/Logo_transparent.png
Kind regards and thank you!
I think It's because you didn't create the file, You can create the file if it doesn't exist by using this code
if(!imageFile.exists()) imageFile.createNewFile();
You're code will look like this
String dir = System.getProperty("user.dir") + "/Logo_transparent.png";
File imageFile = new File(dir);
BufferedImage bufferedImage = null;
try {
if(!imageFile.exists()) imageFile.createNewFile();
bufferedImage = ImageIO.read(imageFile);
} catch (IOException e) {
System.out.println(e.getMessage());
System.out.println(dir);
System.out.println();
}
Also you shouldn't concat child files like that instead pass it as a second argument.
File imageFile = new File(System.getProperty("user.dir"), "Logo_transparent.png");
If your image files will be packaged together with your class files (for example in the same .jar) you should not use File but read it as a resource:
bufferedImage = ImageIO.read(this.getClass().getResourceAsStream("/Logo_transparent.png"));
Notice the '/' before the file name. This means to search in the root path of the classpath.
If you specify without / it will search in the package of this (the current class)
this.getClass().getResourceAsStream("Logo_transparent.png")
You can try to build the absolute path to the image like here and read it afterward.

URI not hierarchical need to use File class for a method

I need to open a video file with my code, and it works perfectly fine in Eclipse but when I export into a runnable JAR, i get an error "URI not hierarchical".
I have seen people suggest using getResourceAsStream(), but i need to have a file object as i am using Desktop.getDesktop.open(File). Can anyone help me out?
Here is the code:
try {
URI path1 = getClass().getResource("/videos/tutorialVid1.mp4").toURI();
File f = new File(path1);
Desktop.getDesktop().open(f);
} catch (Exception e) {
e.printStackTrace();
}
if it helps my folder list is like
Src
videos
videoFile.mp4
EDIT:
I plan to run this on windows only, and use launch4j to create an exe.
You can copy the file from the jar to a temporary file and open that.
Here's a method to create a temporary file for a given jar resource:
public static File createTempFile(String path) {
String[] parts = path.split("/");
File f = File.createTempFile(parts[parts.length - 1], ".tmp");
f.deleteOnExit();
try (Inputstream in = getClass().getResourceAsStream(path)) {
Files.copy(in, f.toPath(), StandardCopyOption.REPLACE_EXISTING);
}
return f;
}
And here's an example of how you'd use it:
Desktop.getDesktop().open(createTempFile("/videos/tutorialVid1.mp4"));

How to Read a File From Any Computer (Java)

Currently I have code like this in my program:
BufferedImage ReadPicture = null;
try {
ReadPicture = ImageIO.read(new File("C:/Users/John/Documents/NetBeansProjects/Program5/build/classes/Program5/Pictures/TestPicture.png"));
} catch (IOException e) {
}
If I compile my file to a jar and give it to someone else, the program does not work as the classpath is specific to my computer. How can I change how I access files/images so that it works on all computers?
For ImageIO in particular, if you always want to read an image from the classpath, without regard to what the classpath actually is, then you can do this:
BufferedImage readPicture = null;
URL imageUrl = getClass().getClassLoader().getResource(
"/Program5/files/Pictures/TestPicture.png");
// Or
// InputStream imageStream = getClass().getClassLoader().getResourceAsStream(
// "/Program5/files/Pictures/TestPicture.png");
// null if not found
try {
readPicture = ImageIO.read(imageUrl);
// null if the image format is unrecognized
} catch (IOException e) {
// ...
}
That relies on the fact that ImageIO can obtain images via URLs. This approach can be used even if the image is packaged in a Jar file, along side your classes (or not).
You can add a folder in your project named files or anything you want.You can make sub-directories in it and arrange files in that.They will be available when you will share it with others.In the code below,"." represents working directory.So make sure the directory structure you are providing,is correct.Try something like this.
BufferedImage ReadPicture = null;
try {
ReadPicture = ImageIO.read(new File("./files/Pictures/TestPicture.png"));
} catch (IOException e) {
}
See Also
Java Project Folder Structure

Java read file within static method, using ClassLoader gives FileNotFoundException

I want to read a file in my java class. My question is similar to this one, but there are two differences. first, I use a different project layout:
/src/com/company/project
/resources
In the resources folder I have a file called "test.txt":
/resources/test.txt
In the project folder I have a class test.java
/src/com/company/project/test.java
I want mu java class to be able to read the contents of test.txt in a STATIC METHOD. I've tried the following:
private static String parseFile()
{
try
{
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
String fileURL = classLoader.getResource("test.txt").getFile();
File file = new File(fileURL);
...
}
}
and the following paths:
File file1 = new File("test.txt");
File file2 = new File("/test.txt");
File file3 = new File("/resources/test.txt");
But they all throw a FileNotFoundException when I want to read the file. How can I correctly declare the path to my file in the snippet above with respect to my project setup and the fact that the method needs to be static?
You should use the class loader of the class which is in the same JAR as the resource instead of the TCCL. And then you need to specify the name of the resource with a full path. And it is typically not good to access those as files. Just open it directly for read (or copy it to a temp file if you need to):
InputStream is =
Project.class.getClassLoader().getResourceAsStream("/resource/test.txt");
BTW: if you simply want to open a file, you need to use a relative file name. This is searched relative to the start dir, which is normally the project main dir (in eclipse):
File resource = new File("resource/test.txt");
(but this wont work if you package it up as a JAR).
After endless trials, I gave up on ClassLoader and getResource methods of any kind.
Absolutely nothing worked, especially if the opening attempt was made from another project. I always ended up getting the bin folder instead of the src folder.
So I devised the following work around:
public class IOAccessory {
public static String getProjectDir() {
try {
Class<?> callingClass = Class.forName(Thread.currentThread().getStackTrace()[2].getClassName());
URL url = callingClass.getProtectionDomain().getCodeSource().getLocation();
URI parentDir = url.toURI().resolve("..");
return parentDir.getPath();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (URISyntaxException e) {
e.printStackTrace();
}
return "";
}
}
The getProjectDir method returns the physical path of the project from which it was called, e.g. C:/workspace/MyProject/.
After that, all you need to do is concatenate the relative path in MyProject of your resource file to open the stream:
public void openResource() throws IOException {
InputStream stream = null;
String projectDir = IOAccessory.getProjectDir();
String filePath = "resources/test.txt";
try {
stream = new FileInputStream(projectDir + filePath);
open(stream);
} catch(Exception e) {
e.printStackTrace();
} finally {
if (stream != null)
stream.close();
}
}
This technique works whether the openResource method is static or non-static, and whether it is called from within the project or from another project on the build path.
It really depends on how your IDE generates output from your project. Typically, classloaders load resources relative to the invoking classes, but if treated right, 'resources' will just end up in the 'root' of your output folder hierarchy, and you can access them accordingly.
For example, if I recreate your code in IntelliJ IDEA, in a class called com/acme/TestClass.class, the following output structure is generated within the IDE when building. This assumes I have "test.txt" sitting in a folder I called "resources", and that folder is specified as being a "resources root":
/com
/acme
TestClass.class
test.txt
The text file ends up in the output folder's root, so accessing it is simple. The following code works for me when I attempt to load the file in a static method within TestClass:
ClassLoader cl = TestClass.class.getClassLoader();
InputStream is = cl.getResourceAsStream("test.txt");
The only thing not covered in the other answers is that your URL conversion to file might not work correctly. If the directories above your project contain a characters that must be decoded then your call to 'getResource("test.txt").getFile()' is not giving you a valid java.io.File path.
I load shader for openGL ES from static function.
Remember you must use lower case for your file and directory name, or else the operation will be failed
public class MyGLRenderer implements GLSurfaceView.Renderer {
...
public static int loadShader() {
// Read file as input stream
InputStream inputStream = MyGLRenderer.class.getResourceAsStream("/res/raw/vertex_shader.txt");
// Convert input stream to string
Scanner s = new Scanner(inputStream).useDelimiter("\\A");
String shaderCode = s.hasNext() ? s.next() : "";
}
...
}
Another method to convert input stream to string.
byte[] bytes;
String shaderCode = "";
try {
bytes = new byte[inputStream.available()];
inputStream.read(bytes);
shaderCode = new String(bytes);
}
catch (IOException e) {
e.printStackTrace();
}

Java input == null why?

I'm using a simple way to get my resources for the project. I'm using Eclipse, and I have a 'res' folder to hold the needed files. This is how I load stuff, for example a 'puppy.png' just in my res folder (no subfolders):
String path = "/puppy.png";
try {
BufferedImage image = ImageIO.read(getClass().getResourceAsStream(path));
} catch(Exception ex) { ex.printStackTrace(); }
And sometimes I get an input==null error, and sometiomes not! Not like this time puppy.png loaded but next time it won't. For some classes it always loads correctly, and for the other classes I always get this error. Can anyone explain why can this happen, and how can I fix it, but still use the getResourceAsStream() method?
Please have a look at How to retrieve image from project folder?.
I have mentioned no of ways to read image from different paths.
You can try any one
// Read from same package
ImageIO.read(getClass().getResourceAsStream("c.png"));
// Read from absolute path
ImageIO.read(new File("E:\\SOFTWARE\\TrainPIS\\res\\drawable\\c.png"));
// Read from images folder parallel to src in your project
ImageIO.read(new File("images\\c.jpg"));
In your case the image must be in the same package where is the class and don't prefix /.
Note that if the resource returns null (meaning it doesn't exist), you will get this error.
Check the input returned like so:
String path = "/puppy.png";
try {
InputStream is = getClass().getResourceAsStream(path);
if (is == null) {
//resource doesn't exist
} else {
BufferedImage image = ImageIO.read(is);
}
} catch(Exception ex) { ex.printStackTrace(); }
Note that you most likely should be using String path = "puppy.png", seeing as you will already be in the content of the project folder.

Categories