Saturday, June 28, 2008

Loading Images From a Jar File

Something Cool To Do With Jar Files

It's pretty simple really, of course there are a few ways to do it. I have seen it done in the following way.
someclass.getClass().getClassLoader().
     getResource(myResourceFileName);
I have had a lot of problems with this type of loading and I prefer a more direct approach which many people don't either know about or care to recommend for one reason or another. Here is how I tend to load images:
private Image fetchImage( String path ) {
  try {
   URL imgUrl = 
    new URL("jar:"+getJarPath()+"!"+path);
   return (new ImageIcon(imgUrl)).getImage();
  } catch (MalformedURLException e) {
   e.printStackTrace();
   
  }
  return null;
 }
The main thing to note here is simply the "jar:" prefix to the jar file path string and the "!" suffix which indicates that anything after it is a location within the jar file itself.

Note: To get to subdirectories the path string must be something like this "/data/images/myimage.png". Therefore the entire URL would look something like the following: "jar:file:/C:MyProject/LoadingFromAJar/myJar.jar!/data/images/myimage.png"

The only downfall to using this method is that it requires you to know the name of the jar file that the image is within. The plus side to this is that your images can be located in any number of subdirectories within the jar file you can package all the contents of your jar file into separate directories without worrying about where they are located or if the Class Loader can find them or not.

Standalone versus Applets

So now that you can load resources from within a Jar file at runtime how can we make it easier to get the location of the Jar file because we need a complete and valid URL which means no relative paths.

So there are two situations we must account for separately. One is a jar file run using the command line or auto-executed as a standalone local application. For this we simply use a File instance:
String myJarFilePath = (new File("")).toURI().toURL().toExternalForm() + "MyJarFile.jar";
This works perfectly fine if you are running the jar file locally but in an Applet you will get a Security exception since you are not allowed to instantiate File class instances. But the Applet class gives you a way to determine the path.
String myJarFilePath = getCodeBase() + "MyJarFile.jar";
The above will only work in an Applet if it is done within or after the Applets init() method is called.

Package this all up into a nice ResourceManager and viola working code that you will never have to touch again and can reuse in any project at anytime. I will post a simple ImageManager class example for your use very soon.

No comments:

Post a Comment