We oftenCodeRead some resource files (such as video, music, text, etc ). These simple operations are certainly not problematic when running them separately. However, if we compress the code into a jar package, even if we package the resource files together, these things cannot be found. Take a look at the following code:
Java code
-
- //Source code1:
-
- PackageEdu. hxraid;
-
- ImportJava. Io .*;
-
- Public ClassResource {
- PublicVoidGetresource ()ThrowsIoexception {
-
- File file =NewFile ("Bin/resource/res.txt");
-
- Bufferedreader BR =NewBufferedreader (NewFilereader (File ));
-
- String S ="";
- While(S = Br. Readline ())! =Null)
-
- System. Out. println (s );
-
- }
-
- }
This code is written in the Java project created by eclipse. Its Directory is: (put the resource file res.txt under the bin directory to compress it into a jar package)
1. src/
Src/edu/hxraid/resource. Java
2. bin/
Bin/resource/res.txt
Bin/edu/hxraid/resource. Class
Obviously, the source code 1 is able to find the resource file res.txt. However, after we compress the entire project into a jar package (resourcejar. Jar), the directory in this jar package is:
Edu/hxraid/resource. Class
Resource/res.txt
In this case, the resource. Class bytecode in the jar package: LDC <string "bin/resource/res.txt"> [20] will not be positioned on the res.txt location in the jar package. Even if you remove the bin/directory: LDC <string "resource/res.txt"> [20], it still cannot be positioned on res.txt in the jar package.
This is mainly because the jar package is a separate file rather than a folder, and it is absolutely impossible to use "file:/E :/.../Resourcejar. Jar/Resource/Res.txt "this form of file urlto locate res.txt. Therefore, even the relative path cannot be located in the TXT file in the jar file (the reader may be confused about the reason, and we will further elaborate on the result of running a piece of code below ).
Then, the resources are imported into the jar package, regardless of the path of resourcejar. jar in the system, the bytecode in the jar packageProgramYou can find the resources in this package. Is this an illusion?
Of course not. We can use classloader to do this:
(1)
Classloader is an abstract class of the class loader. It dynamically obtains the running information of the loaded class at runtime.In this case, when we call the resource class in resourcejar. jar, the JVM loads the resource class and records the resource runtime information (including the path of the jar package where the resource is located ). The methods in the classloader class can help us dynamically obtain the information:
● Public URL getresource (string name)
Search for resources with a given name. Resources are some data (images, sounds, text, etc.) that can be accessed in a way unrelated to the code base through class code ). And return the URL object of the resource.
● Public inputstream getresourceasstream (string name );
Returns the input stream for reading the specified resource.This method is very important. You can directly obtain the content of the files in the jar package.
(2)
Classloader is abstract, and objects cannot be instantiated. It is also impossible to call the above two methods through classloader.Therefore, when writing code, we use the getresource () and getresourceasstream () methods in the class. These two methods will delegate the getresource () and getresourceasstream () methods in the classloader.. Now let's re-write a resource code to see what the above confusing words mean:
Java code
-
- // Source code 2:
-
- PackageEdu. hxraid;
-
- ImportJava. Io .*;
- ImportJava.net. url;
-
- Public ClassResource {
-
- PublicVoidGetresource ()ThrowsIoexception {
-
- // Search for the URL of the specified resource, in which the res.txt is still in the bin directory
- URL fileurl =This. Getclass (). getresource ("/Resource/res.txt");
-
- System. Out. println (fileurl. GetFile ());
-
- }
-
- Public Static VoidMain (string [] ARGs)ThrowsIoexception {
-
- Resource res =NewResource ();
- Res. getresource ();
-
- }
-
- }
Run the following source code:/E:/code_factory/Wanwan/bin/resource/res.txt(../Code_factory/Wanwan /..Is Java
Path of the project)
We package this code into resourcejar. jar, and place resourcejar. jar in other paths (such as c: \ resourcejar. Jar ). Create a Java project and import resourcejar. jar, and write a test code to call the resource class in the jar package:
Java code
-
- ImportJava. Io. ioexception;
- ImportEdu. hxraid. resource;
-
- Public ClassTest {
-
- Public Static VoidMain (string [] ARGs)ThrowsIoexception {
-
- Resource res =NewResource ();
-
- Res. getresource ();
-
- }
- }
The running result is:File:/C:/resourcejar. Jar! /Resource/res.txt
At runtime, we can see the position of res.txt. However, the question is, can you refer to the following code to access the res.txt file?
File F = new file ("C:/resourcejar. Jar! /Resource/res.txt ");
Of course not possible, because ".../resourcejar. Jar! /Resource/... "is not in the format of file resource locator (jar Chinese source has its special URL format:Jar: <URL>! /{Entry}). Therefore, if the class source code in the jar package uses file
F = new file (relative path);, it is impossible to locate the file resource. This is why the crux of filenotfoundexception is reported when the jar package is called after source code 1 is packaged into a jar file.
(3)
We cannot use regular operations.CompositionTo read the resource file res.txt in resourcejar.jar,However, you can use the getresourceasstream () method of the class to obtainThis method reads the resource files in jar, which is transparent to us. We rewrite resource. Java:
Java code
-
- // Source code 3:
-
- PackageEdu. hxraid;
-
- ImportJava. Io .*;
-
- Public ClassResource {
- Public VoidGetresource ()ThrowsIoexception {
-
- // Return the input stream for reading the specified resource
-
- Inputstream is =This. Getclass (). getresourceasstream ("/Resource/res.txt");
-
- Bufferedreader BR =NewBufferedreader (NewInputstreamreader (is ));
- String S ="";
-
- While(S = Br. Readline ())! =Null)
-
- System. Out. println (s );
-
- }
-
- }
The edu/hxraid/resource. Class file and resource/volume file in the/bin directory of the Java project are used.