Accessing Jar Dependencies - java

I have a jar file that contains an exe and banner image (jpg) that the entire script depends on. How can I access and use these 2 dependencies from itself (the jar file)? Currently the jpg is accessed by:
BufferedImage getBanner = ImageIO.read(new File("banner.jpg"));
JLabel drawBanner = new JLabel(new ImageIcon(getBanner));
and the exe is accessed by:
String cmd = "exe [params]";
Runtime run = Runtime.getRuntime();
Process pr = run.exec(cmd);
I might even host the banner image online and just have it pull it from there, so I can dynamically update that.

The Classloader for the jre can "find" any file in your classpath.
To add an external program, so that its accessible to your jar :
First create a class loader and use your ClassLoader to get the resource dynamically, and let it handle the path specific details of the file location. Thus ... you will do something like this :
URL myExecutable =
MyClass.class.getClassLoader().getResource("executable/program.exe");
Now, you should be able to DIRECTLY access the program , as if it is any other file.
File f=new File(myExecutable.toURI());
And now you can call it using
Runtime.getRuntime().exec(f.getAbsolutePath());
CAVEAT
At this point, ask yourself WHY AM I BUNDLING AN EXE IN A JAR FILE ? Better to have a separate package for each operating system platform, in a zip file. Put the jar and the exe in a zip file --- rather than bundling the OS specific executable to your java binary.

Related

Passing a .JAR program (ran from terminal) a text file as input

I have created a java program that other testers will use to help with their testing. I will be sending them a zip file with the .jar, a readme.txt, and main.properties.txt file.
The main.properties.txt file is a template for the testers to input their DB access credentials. They will update the main.properties file with their db cred's and then attempt to run the .jar from the terminal or command line. The issue I am running into is this. My program needs this updated main.properties.txt file so it can create the connections to our DB's.
What instructions do I need to give in my readme so my program can successfully find the main.properties.txt? Does the main.properties need to be in the same directory as the .jar? Can the testers just create a file on their desktop or documents folders to put the .jar and main.props?
The other question I have is how do I pass this file to my program once its ran from the terminal? Currently it is really easy, because the main.props is part of my program and I can just do something like
Properties prop = new Properties();
FileInputStream in = new FileInputStream("src/main/resources/main.properties");
prop.load(in);
in.close();
But now main.properties is not part of the project anymore. I don't know how to change the code above so that it can find the text from a directory on the local. The location in which they wish to put their main.properties is out of my control so writing a static path will not work. Please help!
There are many ways, I'll show you two.
You need a File object that points to the main.properties file. Then you create a stream on this object new FileInputStream(File) , as you already did by using a String.
The problem of course is to get a relative path to main.properties.txt which works on all systems, regardless where the jar-File is located.
1. Desktop
In this case the main.properties.txt is located at the users desktop. Here is how you access it:
File desktop = new File(System.getProperty("user.home"), "Desktop");
File target = new File(desktop, "main.properties.txt");
Alernativly, if you plan to distribute configuration and property files that do not require user interaction, you may want to use locations like Temp or Documents (Windows).
2. Relative to the jar
Probably one of your best options. Assume the target is in the same folder than the jar-File (or at least in a fix structure relative to the jar). Here is how you access it (related question: how-to-get-the-path-of-a-running-jar-file):
CodeSource codeSource = YourMainClass.class.getProtectionDomain().getCodeSource();
File jarFile = new File(codeSource.getLocation().toURI().getPath());
File jarDir = jarFile.getParentFile();
File target = new File(jarDir, "main.properties.txt");

Can't read input file when compressed as a jar

I am trying to run a jar file in terminal when I get this error:
I can run this file fine in my IDE, but when I export the project as a jar, it cannot find the file. Here is the code that the error points to:
BufferedImage buttonIcon = ImageIO.read(new File("img/button.png"));
button = new JButton(new ImageIcon(buttonIcon));
There are two issues.
You need to put the file into the jar.
You need to use getResourceAsStream(...) to use the class loader to load from the jar.
To verify the image presence in the jar file, use the command jar -tf jarfile.jar and see if button.png is in the jar, where it is expected. If it is not, look into altering your jar packaging.
As for the getResourceAsStream(...) there are many who have already offered how to do this properly. Look to their answers.
If you want to read that file from inside your JAR use:
BufferedImage buttonIcon = ImageIO.read( getClass().getResourceAsStream("/classpath/to/my/file"));
Try this one:
String imgPath = "img/button.png";
BufferedImage buffImage = ImageIO.read(getClass().getResourceAsStream(imgPath));
Use the following:
ImageIO.read(getClass().getClassLoader().getResource(path));
make sure the path doesn't contain the src folder (but keep the images in the actual folder)
path = "image.jpg";

Java won't export my resources properly

So I have 2 class folders one is res the other is lib. My res folder has two other sub folders one with images the other with sounds. My lib folder has 4 other jar files and a native folder. It all works within eclipse but when I try to export it as a runnable jar it does not work. I won't won't recognize anything.
I am to call my images I am using ImageIO.read(new File(imagePath)); For the sound I am using the external libraries I mentioned earlier to load and play them.
I am to call my images I am using ImageIO.read(new File(imagePath))
Contrary to your title, this is not an Eclipse problem - it's simply a bug in your code, because your code assumes that the image is stored as a file in the file system, when it's not.
You don't have a file for the image, so you shouldn't use new File. You should instead use Class.getResource or ClassLoader.getResource - or the getResourceAsStream equivalents. That way, it will load the resource from whatever context the class itself is loaded, which is appropriate for jar files. So for example, you might have:
Image image = ImageIO.read(MyClass.getResource("foo.png"));
... where foo.png is effectively in the same package structure as the class. Alternatively:
Image image = ImageIO.read(MyClass.getResource("/images/foo/bar.png"));
where images is a folder within the root directory of one of your jar files loaded by the same ClassLoader. (We don't have enough information to give you complete code here, but that should be enough to get you going.)

How can I create a flexible medium for accessing png/bmp files with code so my code will run in Eclipse, as well as after it is exported?

I am making an application that searches the screen for a specific image. I read the picture (file) I am scanning for and convert it to a buffered image, then to an int[] so I can process it faster. I also use the robot class to take a screenshot and convert to an int[].
While running code in Eclipse and having the files in the source folder, I don't have any problems. But after exporting my code to a runnable jar file, my scanning methods no longer work. I think it might have something to do with compression because my pictures need to be exactly how they were taken.
The only success I have had with a "finished format" is by exporting the jar normally, and using a folder in the same directory called images to hold the files. Using this code:
File img = new File(System.getProperty("user.dir") + File.separator + "images" + File.separator + "Close.bmp");
When running directly from eclipse I can simply do this:
File img = new File(src/Close.bmp);
Any suggestions? Maybe some tips/settings on exporting jars?
You have various options:
probably the easiest is to put the image in the classpath, i.e. deploy it with your class files, probably within a jar file. The drawback is that you can't replace the image (as long as you don't want your user to fiddle with the classpath)
place it relative to the user.dir as you have done, in this case you need to understand what the user.dir actually is: The working directory from which your application got started. It will differ depending on how you start it.
another option is to use a path relative to user.home which is your home directory.

Absolute/relative path in java (jar, ide)

My program uses Image.class, which helps me recieve image.
Image img = new ImageIcon("Shooter2D/res/background.jpg").getImage();
When the program is run from the development environment - everything works, after compiling a jar file - does not work.
Tell me how to properly set the path to work in the IDE (Intellij IDEA) and in the archive.
Shooter2D.jar contain:
- META-INF
Manifest-Version: 1.0
Main-Class: Shooter2Dv22082013.Main
- res
all pictures
- Shooter2Dv22082013
all .class files, main is Main.class
indicative figure: http://imageshack.us/photo/my-images/801/eyjv.png/
Here's what the javadoc says about the constructor of ImageIcon:
Creates an ImageIcon from the specified file. The image will be preloaded by using MediaTracker to monitor the loading state of the image. The specified String can be a file name or a file path.
(emphasis mine)
Your image is not stored in a file. It isn't in your file system. It's in a jar that is itself in the classpath. And that's where you want to load it from. Wherever the jar file of your application is on the end-user's machine, your program wants to load it from this jar file. And all the resources in this jar file are available from the ClassLoader.
So you should use
new ImageIcon(MyClass.class.getResource("/res/background.jpg"))
or
new ImageIcon(MyClass.class.getClassLoader().getResource("res/background.jpg"))

Categories