Probe into the resource problem in the Read JAR package

Source: Internet
Author: User
Tags file url

Recently write a program executable jar, the program contains 2 resource packages, one is images, and one is files. The problem is, when developing in eclipse, there is no problem when using the file class to get the files below the documents. However, when the program is exported as a runnable jar, an exception is thrown when the program is run, and File not found. Let's explore.

The first is my project directory structure:

Program to access the image code under images:

[Java]View Plaincopyprint?
    1. Seticonimage (new ImageIcon (this.getclass (). GetResource (
    2. "/images/icon.png")).  GetImage ());

As a result, in Eclipse and exported jar packages, it runs fine. Note that the file class is not used here.

The program uses the file class to access the resource code under the Files folder:

[Java]View Plaincopyprint?
    1. File F = new File (infoutils.   Class.getclass (). GetResource ("/files/news.ini"). GetPath ());

As a result, working properly in eclipse, the exported jar package throws an exception.

Then try the following method in the jar package to obtain the News.ini, the result declares the failure.

[Java]View Plaincopyprint?
  1. System.out.println ("*************path test**************");
  2. System.out.println (infoutils.   Class.getResource (""). GetPath ());
  3. System.out.println (infoutils.   Class.getResource ("/"). GetPath ());
  4. System.out.println (infoutils.   Class.getclassloader (). GetResource (""));
  5. System.out.println (new File ("/files"). GetAbsolutePath ());
  6. System.out.println (new File ("/files"). GetPath ());
  7. System.out.println (new File ("/files"). GetPath ());
  8. System.out.println (new File (""). GetAbsolutePath ());
  9. System.out.println (new File (""). Getcanonicalpath ());
  10. System.out.println (System.getproperty ("Java.class.path"));
  11. System.out.println ("*************path test**************");

Let us analyze, mainly because the jar package is a separate file rather than a folder, it is absolutely impossible to "File:/e:/.../xxx.jar/files/news.ini" This form of file URL to locate News.ini. Therefore, even a relative path cannot locate the INI file within the jar file (the reader may be puzzled by the reason for this explanation, and we will use the result of a code run to further illustrate).

Then the resource into the jar package, no matter what path Resourcejar.jar in the system, the bytecode program in the jar package can find the resources in the package. Is this going to be a fantasy? Of course not, we can use the class loader (ClassLoader) to do this:

(1) ClassLoader is an abstract class of Class loaders.

It can dynamically get the run information of the load class at run time. It can be said that when we call the resource class in Resourcejar.jar, the JVM loads into the resource class and records the resource runtime information (including the path information for the jar package where resource is located). The methods in the ClassLoader class can help us to obtain this information dynamically:
Public URL getresource (String name)
Finds a resource with the given name. A resource is some data (images, sounds, text, and so on) that can be accessed through class code in a code-base-independent manner. and returns the URL object for the resource.
Public Inputstreamgetresourceasstream (String name);
Returns the input stream that reads the specified resource. This method is important to get the contents of the files in the jar package directly.

(2) ClassLoader is abstract, it is impossible to instantiate an object, it is more impossible to call the above two methods through ClassLoader. So when we actually write the code, it's through the GetResource () and getResourceAsStream () methods in the class classes, and these two methods delegate the GetResource () in ClassLoader and getResourceAsStream () method. Well, now we re-write a resource code to see what the above puzzling words mean:

[Java]View Plaincopyprint?
  1. Import java.io.*;
  2. Import Java.net.URL;
  3. Public class Resource {
  4. public void GetResource () throws ioexception{
  5. //Find the URL of the specified resource, where Res.txt still starts in the bin directory
  6. URL fileurl=This.getclass (). GetResource ("/resource/res.txt");
  7. System.out.println (Fileurl.getfile ());
  8. }
  9. public static void Main (string[] args) throws IOException {
  10. Resource res=New Resource ();
  11. Res.getresource ();
  12. }
  13. }


Run this source code result:/e:/code_factory/wanwan/bin/resource/res.txt (.. /code_factory/wanwan/. is the path where the Javaproject is located).

We package this code into Resourcejar.jar and place the Resourcejar.jar under other paths (such as C:\ResourceJar.jar). Then create another javaproject and import the Resourcejar.jar to write a test code that calls the resource class in the JAR package:

[Java]View Plaincopyprint?
  1. Import java.io.IOException;
  2. Import xx. Resource;
  3. Public class TEST {
  4. public static void Main (string[] args) throws IOException {
  5. Resource res=New Resource ();
  6. Res.getresource ();
  7. }
  8. }

The result of this operation is: File:/c:/resourcejar.jar!/resource/res.txt.

We managed to get the res.txt position dynamically at run time. However, the question comes, can you get the Res.txt file using the code below?

File f=newfile ("C:/resourcejar.jar!/resource/res.txt");
Of course not, because ".../resourcejar.jar!/resource/..." is not the format of the file resource Locator (the resource in the jar has its own special URL form: Jar:<url>!/{entry}). Therefore, if the class source code in the jar package is in the form of a filef=newfile (relative path), it is not possible to locate the file resource. This is why when the source code 1 is packaged into a jar file, it is reported that the FileNotFoundException is the crux of the call to the jar package.

(3) We can not use the normal operation of the file method to read the resource file Res.txt in Resourcejar.jar, but it is available through the class getResourceAsStream () method, this method is how to read the resource file in the jar, This is transparent to us. We rewrite the Resource.java into:

[Java]View Plaincopyprint?
  1. Import java.io.*;
  2. Public class Resource {
  3. public void GetResource () throws ioexception{
  4. //Returns the input stream that reads the specified resource
  5. InputStream is=This.getclass (). getResourceAsStream ("/resource/res.txt");
  6. BufferedReader br=New BufferedReader (new InputStreamReader (IS));
  7. String s="";
  8. While ((S=br.readline ()) =null)
  9. System.out.println (s);
  10. }
  11. }


We will edu/hxraid/resource.class and resource files in the/bin directory under Java engineering resource/ Res.txt packaged into the Resourcejar.jar, regardless of the jar package in any directory of the system, call the resource class in the jar package can obtain the Res.txt resources in the jar package, no longer cannot find the Res.txt file.

Something:

Of course now there are jar packages that can be used directly to solve this problem.

Of course, this kind of work, predecessors have already been studied. In Xwork, there is a tool class called Classloaderutil, which allows you to drill down into the resource files in the jar package. STRUTS2 is using this tool class to read all the struts-default.xml in the plugin. For example, a user can download Xwork-core-2.1.4-jdk14.jar, which includes a class Classloaderutil.java, where the static function

getResourceAsStream (String resourcename,class Callingclass) can also solve this problem.

Classloaderutil.getresourceasstream ("Wei.txt", String.class);

Probe into the resource problem in the Read JAR package

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.