Java - Running JAR refuses to load file in the same directory - java

Quick one. I'm trying to deploy a program, which borks at the following code. I want to read a properties file named, adequately, properties.
Properties props = new Properties();
InputStream is;
// First try - loading from the current directory
try {
File f = new File("properties");
is = new FileInputStream(f);
} catch (FileNotFoundException fnfe) {
fnfe.printStackTrace(System.err);
is = null;
}
try {
if (is == null) {
// Try loading from classpath
is = getClass().getResourceAsStream("properties");
}
//Load properties from the file (if found), else crash and burn.
props.load(is);
} catch (IOException e) {
e.printStackTrace(System.err);
}
Everything goes well when I run the program through Netbeans.
When I run the JAR by itself, though, I get two exceptions.
java.io.FileNotFoundException: properties (The system cannot find the file specified)
at java.io.FileInputStream.open(Native Method)
at java.io.FileInputStream.<init>(Unknown Source)
.
.
.
Exception in Application start method
Exception in Application stop method
java.lang.reflect.InvocationTargetException
.
.
.
(exception during props.load(is) because is == null)
I'm running the file from the "dist" folder. I've tried placing the properties file inside the folder with the jar, without result. Normally, the properties file is located in the root project folder.
Any ideas?

You read your file as a resource (getResourceAsStream("properties");). So it must be in the classpath. Perhaps in the jar directly or in a directory which you add to the classpath.
A jar is a zip file so you can open it with 7zip for example add your properties file to the jars root level and try it again.

Thanks to the comments, I built an absolute path generator based on the current run directory of the jar. Props to you, guys.
private String relativizer(String file) {
URL url = RobotikosAnomologitos.class.getProtectionDomain().getCodeSource().getLocation();
String urlString = url.toString();
int firstSlash = urlString.indexOf("/");
int targetSlash = urlString.lastIndexOf("/", urlString.length() - 2) + 1;
return urlString.substring(firstSlash, targetSlash) + file;
}
So my new file-reading structure is:
Properties props = new Properties();
InputStream is;
// First try - loading from the current directory
try {
File f = new File("properties");
is = new FileInputStream(f);
} catch (FileNotFoundException fnfe) {
fnfe.printStackTrace(System.err);
is = null;
}
try {
if (is == null) {
// Try loading from classpath
String pathToProps = relativizer("properties");
is = new FileInputStream(new File(pathToProps));
//is = getClass().getResourceAsStream(pathToProps);
}
//Load properties from the file (if found), else crash and burn.
props.load(is);
} catch (IOException e) {
e.printStackTrace(System.err);
}
// Finally parse the properties.
//code here, bla bla

Related

Android Studio write to .properties file

I followed Where to put own properties file in an android project created with Android Studio? and I got an InputStream which reads from my .properties file successfully. However, I can't write to that .properties file, as there is no similar method to getBaseContext().getAssets().open ("app.properties") which returns an OutputStream. I have also read Java Properties File appending new values but this didn't seem to help me, my guess is my file name for the file writer is wrong but I also tried "assets\userInfo.properties" which also doesn't work.
My .properties file is in src\main\assets\userInfo.properties
Properties props = new Properties();
InputStream inputStream = null;
try{
inputStream = getBaseContext().getAssets().open("userInfo.properties");
props.load(inputStream);
props.put("name", "smith");
FileOutputStream output = new FileOutputStream("userInfo.properties"); //this line throws error
props.store(output, "This is overwrite file");
String name = props.getProperty("name");
Log.d(TAG, "onCreate: PROPERTIES TEST NAME CHANGE: " + name);
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
Current code throws this error:
java.io.FileNotFoundException: userInfo.properties (Read-only file system)
You can't write to the assets folder, as it is inside the APK which is read-only.
Use internal or external storage instead
You can't write to the assets folder. If you want to update your properties file, you'll have to put them some place else. If you want the initial version in the assets or raw folder, just copy it to the default files dir when the app is first used, then read from/write to it there.

getResourceAsStream() is returning null. Properties file is not loading

I am trying to load properties file. Here is my structure
Now i am trying to load test.properties file. But i am getting null. Here how i am doing
public class Test {
String workingDir = System.getProperty("user.dir");
System.out.println("Current working directory : " + workingDir);
File temp = new File(workingDir + "\\" + "test.properties");
String absolutePath = temp.getAbsolutePath();
System.out.println("File path : " + absolutePath);
Properties properties = null;
try {
properties = new Properties();
InputStream resourceAsStream = Test.class.getClassLoader().getResourceAsStream(absolutePath);
if (resourceAsStream != null) {
properties.load(resourceAsStream);
}
} catch (IOException e) {
e.printStackTrace();
}
System.exit(0);
} //end of class Test
This program prints
Current working directory : D:\Personal Work\eclipse 32 Bit\workspace\Spring Integration\LS360BatchImportIntegration
File path : D:\Personal Work\eclipse 32 Bit\workspace\Spring Integration\LS360BatchImportIntegration\test.properties
But it is not loading properties file from this path. Although it is present there. Why i am getting null ?
Thanks
Edit---
----------------------------
String workingDir = System.getProperty("user.dir");
System.out.println("Current working directory : " + workingDir);
File temp = new File(workingDir, "test.properties");
String absolutePath = temp.getAbsolutePath();
System.out.println("File path : " + absolutePath);
try {
properties = new Properties();
InputStream resourceAsStream = new FileInputStream(temp);
if (resourceAsStream != null) {
properties.load(resourceAsStream);
}
} catch (IOException e) {
e.printStackTrace();
}
System.exit(0);
Current working directory : D:\Personal Work\eclipse 32 Bit\workspace\Spring Integration\LS360BatchImportIntegration
File path : D:\Personal Work\eclipse 32 Bit\workspace\Spring Integration\LS360BatchImportIntegration\test.properties
java.io.FileNotFoundException: D:\Personal Work\eclipse 32 Bit\workspace\Spring Integration\LS360BatchImportIntegration\test.properties (The system cannot find the file specified)
at java.io.FileInputStream.open(Native Method)
at java.io.FileInputStream.<init>(Unknown Source)
at com.softech.ls360.integration.BatchImport.main(BatchImport.java:57)
Oh oh ... There are several problems here:
1) In your first provided code snippet, you are using a ClassLoader for loading a resource file. This is indeed a good decision. But the getResourceAsStream method needs a "class-path relative" name. You are providing an absolute path.
2) Your second code snippet (after edit) results in not being able to find the file "D:...\LS360BatchImportIntegration\test.properties". According to your screenshot, the file should be "D:...\LS360AutomatedRegulatorsReportingService\test.properties". This is another directory.
I fear, that your descriptions are not up to date with the findings on your machine.
But let's just move to a reasonable solution:
1) In your Eclipse project (the screenshot tells us, that you are using Eclipse), create a new directory named "resources" in the same depth as your "src" directory. Copy - or better move - the properties file into it.
2) This new directory must be put into the "build path". Right-click the directory in the Package Explorer or Project Explorer view, select "Build Path", then "Use as Source Folder". Note: This build path will be the class path for the project, when you run it.
3) As the resources directory now is part of your class path and contains your properties file, you can simply load it with getResourceAsStream("test.properties").
EDIT
I just see, that you also use Maven (the pom.xml file). In Maven, such a resources directory exists by default and is part of the build path. It is "src/main/resources". If so, just use this.
Please put your property file in /src/main/resources folder and load from ClassLoader. It will be fix.
like
/src/main/resources/test.properties
Properties properties = null;
try {
properties = new Properties();
InputStream resourceAsStream = Test.class.getClassLoader().getResourceAsStream("test.properties");
if (resourceAsStream != null) {
properties.load(resourceAsStream);
}
} catch (IOException e) {
e.printStackTrace();
}
You are using the class loader (which reads in the classpath) whereas you are using the absolute path.
Simply try:
InputStream resourceAsStream = new FileInputStream(temp);
As a side note, try instanciating your file doing:
File temp = new File(workingDir, "test.properties");
to use the system-dependent path spearator.
I had a similar problem with a file not being found by getResourceAsStream(). The file was in the resources folder (src/main/resources), and still not found.
The problem got resolved when I went into the eclipse Package Explorer and "refreshed" the resources folder. It was in the directory, but Eclipse did not see it until the folder was refreshed (right-click on the folder and select Refresh).
I hope this helps !!
You can keep your test.properties into src/main/resources
public static Properties props = new Properties();
InputStream inStream = Test.class.getResourceAsStream("/test.properties");
try {
loadConfigurations(inStream);
} catch (IOException ex) {
String errMsg = "Exception in loading configuration file. Please check if application.properties file is present in classpath.";
ExceptionUtils.throwRuntimeException(errMsg, ex, LOGGER);
}
public static void loadConfigurations(InputStream inputStream) throws IOException{
props.load(inputStream);
}
You're passing a file path to getResourceAsStream(String name), but name here is a class path, not a file path...
You could make sure the file is on your classpath, or use a FileInputStream instead.

Reading Properties file every time in the execution in Java

I have to read properties file "MyProperty.properties" from "ReadProp.java" class given my the following directory structure of my "war" file I am going to deploy.
MyApp.war
| ----MyProps
| |--MyProperty.properties
|---WEB-INF |
|--classes
|---ReadProp.java
I am going to deploy this "war" file in "Sun portal server". But I should not change any of this directory structure because of the requirement specification.
I am reading this file in the following way
String path = servletContext.getRealPath("/MyProps/MyProperty.properties"); System.out.println("path: " + path);
Properties prop = new Properties();
try {
prop.load(new FileInputStream(path));
);
} catch (Exception e) {
e.printStackTrace();
}
String name= prop.getProperty("name");
It is working fine. but the problem is if I change properties file after loading the application the changes are not reflecting.
I may change the properties file anytime how to do If I want that changes should be reflected . I mean the application should load the properties file everytime in the exexcutio
You won't see changes unless you bounce the app server.
A better choice would be to put the .properties file in your /WEB-INF/classes folder and read it from the CLASSPATH using getResourceAsStream().
You don't say where you're reading the code. You might have to implement a Timer task to periodically wake up and reload the .properties file.
You might also try a WatchService if you're using JDK 7:
Auto-reload changed files in Java
You need to use java 7 WatchService for that Example Link
I got the answer:
String path = servletContext.getRealPath("/MyProps/MyProperty.properties");
System.out.println("path: " + path);
Properties prop = new Properties();
try {
File f = new File(path);
FileInputStream fis = new FileInputStream(f);
prop.load(fis);
}
catch (Exception e) {
e.printStackTrace();
}
The newer way to do this is:
Path path;
try {
path = Paths.get("MyProperty.properties");
if (Files.exists(path)) {
props = new Properties();
props.load(Files.newInputStream(path));
}
} catch (IOException e) {
e.printStackTrace();
}

How can I access a folder inside of a resource folder from inside my jar File?

I have a resources folder/package in the root of my project, I "don't" want to load a certain File. If I wanted to load a certain File, I would use class.getResourceAsStream and I would be fine!! What I actually want to do is to load a "Folder" within the resources folder, loop on the Files inside that Folder and get a Stream to each file and read in the content... Assume that the File names are not determined before runtime... What should I do? Is there a way to get a list of the files inside a Folder in your jar File?
Notice that the Jar file with the resources is the same jar file from which the code is being run...
Finally, I found the solution:
final String path = "sample/folder";
final File jarFile = new File(getClass().getProtectionDomain().getCodeSource().getLocation().getPath());
if(jarFile.isFile()) { // Run with JAR file
final JarFile jar = new JarFile(jarFile);
final Enumeration<JarEntry> entries = jar.entries(); //gives ALL entries in jar
while(entries.hasMoreElements()) {
final String name = entries.nextElement().getName();
if (name.startsWith(path + "/")) { //filter according to the path
System.out.println(name);
}
}
jar.close();
} else { // Run with IDE
final URL url = Launcher.class.getResource("/" + path);
if (url != null) {
try {
final File apps = new File(url.toURI());
for (File app : apps.listFiles()) {
System.out.println(app);
}
} catch (URISyntaxException ex) {
// never happens
}
}
}
The second block just work when you run the application on IDE (not with jar file), You can remove it if you don't like that.
Try the following.
Make the resource path "<PathRelativeToThisClassFile>/<ResourceDirectory>" E.g. if your class path is com.abc.package.MyClass and your resoure files are within src/com/abc/package/resources/:
URL url = MyClass.class.getResource("resources/");
if (url == null) {
// error - missing folder
} else {
File dir = new File(url.toURI());
for (File nextFile : dir.listFiles()) {
// Do something with nextFile
}
}
You can also use
URL url = MyClass.class.getResource("/com/abc/package/resources/");
The following code returns the wanted "folder" as Path regardless of if it is inside a jar or not.
private Path getFolderPath() throws URISyntaxException, IOException {
URI uri = getClass().getClassLoader().getResource("folder").toURI();
if ("jar".equals(uri.getScheme())) {
FileSystem fileSystem = FileSystems.newFileSystem(uri, Collections.emptyMap(), null);
return fileSystem.getPath("path/to/folder/inside/jar");
} else {
return Paths.get(uri);
}
}
Requires java 7+.
I know this is many years ago . But just for other people come across this topic.
What you could do is to use getResourceAsStream() method with the directory path, and the input Stream will have all the files name from that dir. After that you can concat the dir path with each file name and call getResourceAsStream for each file in a loop.
I had the same problem at hands while i was attempting to load some hadoop configurations from resources packed in the jar... on both the IDE and on jar (release version).
I found java.nio.file.DirectoryStream to work the best to iterate over directory contents over both local filesystem and jar.
String fooFolder = "/foo/folder";
....
ClassLoader classLoader = foofClass.class.getClassLoader();
try {
uri = classLoader.getResource(fooFolder).toURI();
} catch (URISyntaxException e) {
throw new FooException(e.getMessage());
} catch (NullPointerException e){
throw new FooException(e.getMessage());
}
if(uri == null){
throw new FooException("something is wrong directory or files missing");
}
/** i want to know if i am inside the jar or working on the IDE*/
if(uri.getScheme().contains("jar")){
/** jar case */
try{
URL jar = FooClass.class.getProtectionDomain().getCodeSource().getLocation();
//jar.toString() begins with file:
//i want to trim it out...
Path jarFile = Paths.get(jar.toString().substring("file:".length()));
FileSystem fs = FileSystems.newFileSystem(jarFile, null);
DirectoryStream<Path> directoryStream = Files.newDirectoryStream(fs.getPath(fooFolder));
for(Path p: directoryStream){
InputStream is = FooClass.class.getResourceAsStream(p.toString()) ;
performFooOverInputStream(is);
/** your logic here **/
}
}catch(IOException e) {
throw new FooException(e.getMessage());
}
}
else{
/** IDE case */
Path path = Paths.get(uri);
try {
DirectoryStream<Path> directoryStream = Files.newDirectoryStream(path);
for(Path p : directoryStream){
InputStream is = new FileInputStream(p.toFile());
performFooOverInputStream(is);
}
} catch (IOException _e) {
throw new FooException(_e.getMessage());
}
}
Another solution, you can do it using ResourceLoader like this:
import org.springframework.core.io.Resource;
import org.apache.commons.io.FileUtils;
#Autowire
private ResourceLoader resourceLoader;
...
Resource resource = resourceLoader.getResource("classpath:/path/to/you/dir");
File file = resource.getFile();
Iterator<File> fi = FileUtils.iterateFiles(file, null, true);
while(fi.hasNext()) {
load(fi.next())
}
If you are using Spring you can use org.springframework.core.io.support.PathMatchingResourcePatternResolver and deal with Resource objects rather than files. This works when running inside and outside of a Jar file.
PathMatchingResourcePatternResolver r = new PathMatchingResourcePatternResolver();
Resource[] resources = r.getResources("/myfolder/*");
Then you can access the data using getInputStream and the filename from getFilename.
Note that it will still fail if you try to use the getFile while running from a Jar.
As the other answers point out, once the resources are inside a jar file, things get really ugly. In our case, this solution:
https://stackoverflow.com/a/13227570/516188
works very well in the tests (since when the tests are run the code is not packed in a jar file), but doesn't work when the app actually runs normally. So what I've done is... I hardcode the list of the files in the app, but I have a test which reads the actual list from disk (can do it since that works in tests) and fails if the actual list doesn't match with the list the app returns.
That way I have simple code in my app (no tricks), and I'm sure I didn't forget to add a new entry in the list thanks to the test.
Below code gets .yaml files from a custom resource directory.
ClassLoader classLoader = this.getClass().getClassLoader();
URI uri = classLoader.getResource(directoryPath).toURI();
if("jar".equalsIgnoreCase(uri.getScheme())){
Pattern pattern = Pattern.compile("^.+" +"/classes/" + directoryPath + "/.+.yaml$");
log.debug("pattern {} ", pattern.pattern());
ApplicationHome home = new ApplicationHome(SomeApplication.class);
JarFile file = new JarFile(home.getSource());
Enumeration<JarEntry> jarEntries = file.entries() ;
while(jarEntries.hasMoreElements()){
JarEntry entry = jarEntries.nextElement();
Matcher matcher = pattern.matcher(entry.getName());
if(matcher.find()){
InputStream in =
file.getInputStream(entry);
//work on the stream
}
}
}else{
//When Spring boot application executed through Non-Jar strategy like through IDE or as a War.
String path = uri.getPath();
File[] files = new File(path).listFiles();
for(File file: files){
if(file != null){
try {
InputStream is = new FileInputStream(file);
//work on stream
} catch (Exception e) {
log.error("Exception while parsing file yaml file {} : {} " , file.getAbsolutePath(), e.getMessage());
}
}else{
log.warn("File Object is null while parsing yaml file");
}
}
}
Took me 2-3 days to get this working, in order to have the same url that work for both Jar or in local, the url (or path) needs to be a relative path from the repository root.
..meaning, the location of your file or folder from your src folder.
could be "/main/resources/your-folder/" or "/client/notes/somefile.md"
Whatever it is, in order for your JAR file to find it, the url must be a relative path from the repository root.
it must be "src/main/resources/your-folder/" or "src/client/notes/somefile.md"
Now you get the drill, and luckily for Intellij Idea users, you can get the correct path with a right-click on the folder or file -> copy Path/Reference.. -> Path From Repository Root (this is it)
Last, paste it and do your thing.
Simple ... use OSGi. In OSGi you can iterate over your Bundle's entries with findEntries and findPaths.
Inside my jar file I had a folder called Upload, this folder had three other text files inside it and I needed to have an exactly the same folder and files outside of the jar file, I used the code below:
URL inputUrl = getClass().getResource("/upload/blabla1.txt");
File dest1 = new File("upload/blabla1.txt");
FileUtils.copyURLToFile(inputUrl, dest1);
URL inputUrl2 = getClass().getResource("/upload/blabla2.txt");
File dest2 = new File("upload/blabla2.txt");
FileUtils.copyURLToFile(inputUrl2, dest2);
URL inputUrl3 = getClass().getResource("/upload/blabla3.txt");
File dest3 = new File("upload/Bblabla3.txt");
FileUtils.copyURLToFile(inputUrl3, dest3);

How to get a path to a resource in a Java JAR file

I am trying to get a path to a Resource but I have had no luck.
This works (both in IDE and with the JAR) but this way I can't get a path to a file, only the file contents:
ClassLoader classLoader = getClass().getClassLoader();
PrintInputStream(classLoader.getResourceAsStream("config/netclient.p"));
If I do this:
ClassLoader classLoader = getClass().getClassLoader();
File file = new File(classLoader.getResource("config/netclient.p").getFile());
The result is:
java.io.FileNotFoundException: file:/path/to/jarfile/bot.jar!/config/netclient.p (No such file or directory)
Is there a way to get a path to a resource file?
This is deliberate. The contents of the "file" may not be available as a file. Remember you are dealing with classes and resources that may be part of a JAR file or other kind of resource. The classloader does not have to provide a file handle to the resource, for example the jar file may not have been expanded into individual files in the file system.
Anything you can do by getting a java.io.File could be done by copying the stream out into a temporary file and doing the same, if a java.io.File is absolutely necessary.
When loading a resource make sure you notice the difference between:
getClass().getClassLoader().getResource("com/myorg/foo.jpg") //relative path
and
getClass().getResource("/com/myorg/foo.jpg")); //note the slash at the beginning
I guess, this confusion is causing most of problems when loading a resource.
Also, when you're loading an image it's easier to use getResourceAsStream():
BufferedImage image = ImageIO.read(getClass().getResourceAsStream("/com/myorg/foo.jpg"));
When you really have to load a (non-image) file from a JAR archive, you might try this:
File file = null;
String resource = "/com/myorg/foo.xml";
URL res = getClass().getResource(resource);
if (res.getProtocol().equals("jar")) {
try {
InputStream input = getClass().getResourceAsStream(resource);
file = File.createTempFile("tempfile", ".tmp");
OutputStream out = new FileOutputStream(file);
int read;
byte[] bytes = new byte[1024];
while ((read = input.read(bytes)) != -1) {
out.write(bytes, 0, read);
}
out.close();
file.deleteOnExit();
} catch (IOException ex) {
Exceptions.printStackTrace(ex);
}
} else {
//this will probably work in your IDE, but not from a JAR
file = new File(res.getFile());
}
if (file != null && !file.exists()) {
throw new RuntimeException("Error: File " + file + " not found!");
}
The one line answer is -
String path = this.getClass().getClassLoader().getResource(<resourceFileName>).toExternalForm()
Basically getResource method gives the URL. From this URL you can extract the path by calling toExternalForm().
I spent a while messing around with this problem, because no solution I found actually worked, strangely enough! The working directory is frequently not the directory of the JAR, especially if a JAR (or any program, for that matter) is run from the Start Menu under Windows. So here is what I did, and it works for .class files run from outside a JAR just as well as it works for a JAR. (I only tested it under Windows 7.)
try {
//Attempt to get the path of the actual JAR file, because the working directory is frequently not where the file is.
//Example: file:/D:/all/Java/TitanWaterworks/TitanWaterworks-en.jar!/TitanWaterworks.class
//Another example: /D:/all/Java/TitanWaterworks/TitanWaterworks.class
PROGRAM_DIRECTORY = getClass().getClassLoader().getResource("TitanWaterworks.class").getPath(); // Gets the path of the class or jar.
//Find the last ! and cut it off at that location. If this isn't being run from a jar, there is no !, so it'll cause an exception, which is fine.
try {
PROGRAM_DIRECTORY = PROGRAM_DIRECTORY.substring(0, PROGRAM_DIRECTORY.lastIndexOf('!'));
} catch (Exception e) { }
//Find the last / and cut it off at that location.
PROGRAM_DIRECTORY = PROGRAM_DIRECTORY.substring(0, PROGRAM_DIRECTORY.lastIndexOf('/') + 1);
//If it starts with /, cut it off.
if (PROGRAM_DIRECTORY.startsWith("/")) PROGRAM_DIRECTORY = PROGRAM_DIRECTORY.substring(1, PROGRAM_DIRECTORY.length());
//If it starts with file:/, cut that off, too.
if (PROGRAM_DIRECTORY.startsWith("file:/")) PROGRAM_DIRECTORY = PROGRAM_DIRECTORY.substring(6, PROGRAM_DIRECTORY.length());
} catch (Exception e) {
PROGRAM_DIRECTORY = ""; //Current working directory instead.
}
This is same code from user Tombart with stream flush and close to avoid incomplete temporary file content copy from jar resource and to have unique temp file names.
File file = null;
String resource = "/view/Trial_main.html" ;
URL res = getClass().getResource(resource);
if (res.toString().startsWith("jar:")) {
try {
InputStream input = getClass().getResourceAsStream(resource);
file = File.createTempFile(new Date().getTime()+"", ".html");
OutputStream out = new FileOutputStream(file);
int read;
byte[] bytes = new byte[1024];
while ((read = input.read(bytes)) != -1) {
out.write(bytes, 0, read);
}
out.flush();
out.close();
input.close();
file.deleteOnExit();
} catch (IOException ex) {
ex.printStackTrace();
}
} else {
//this will probably work in your IDE, but not from a JAR
file = new File(res.getFile());
}
if netclient.p is inside a JAR file, it won't have a path because that file is located inside other file. in that case, the best path you can have is really file:/path/to/jarfile/bot.jar!/config/netclient.p.
You need to understand the path within the jar file.
Simply refer to it relative. So if you have a file (myfile.txt), located in foo.jar under the \src\main\resources directory (maven style). You would refer to it like:
src/main/resources/myfile.txt
If you dump your jar using jar -tvf myjar.jar you will see the output and the relative path within the jar file, and use the FORWARD SLASHES.
In my case, I have used a URL object instead Path.
File
File file = new File("my_path");
URL url = file.toURI().toURL();
Resource in classpath using classloader
URL url = MyClass.class.getClassLoader().getResource("resource_name")
When I need to read the content, I can use the following code:
InputStream stream = url.openStream();
And you can access the content using an InputStream.
follow code!
/src/main/resources/file
streamToFile(getClass().getClassLoader().getResourceAsStream("file"))
public static File streamToFile(InputStream in) {
if (in == null) {
return null;
}
try {
File f = File.createTempFile(String.valueOf(in.hashCode()), ".tmp");
f.deleteOnExit();
FileOutputStream out = new FileOutputStream(f);
byte[] buffer = new byte[1024];
int bytesRead;
while ((bytesRead = in.read(buffer)) != -1) {
out.write(buffer, 0, bytesRead);
}
return f;
} catch (IOException e) {
LOGGER.error(e.getMessage(), e);
return null;
}
}
A File is an abstraction for a file in a filesystem, and the filesystems don't know anything about what are the contents of a JAR.
Try with an URI, I think there's a jar:// protocol that might be useful for your purpouses.
The following path worked for me: classpath:/path/to/resource/in/jar
private static final String FILE_LOCATION = "com/input/file/somefile.txt";
//Method Body
InputStream invalidCharacterInputStream = URLClassLoader.getSystemResourceAsStream(FILE_LOCATION);
Getting this from getSystemResourceAsStream is the best option. By getting the inputstream rather than the file or the URL, works in a JAR file and as stand alone.
It may be a little late but you may use my library KResourceLoader to get a resource from your jar:
File resource = getResource("file.txt")
Inside your ressources folder (java/main/resources) of your jar add your file (we assume that you have added an xml file named imports.xml), after that you inject ResourceLoader if you use spring like bellow
#Autowired
private ResourceLoader resourceLoader;
inside tour function write the bellow code in order to load file:
Resource resource = resourceLoader.getResource("classpath:imports.xml");
try{
File file;
file = resource.getFile();//will load the file
...
}catch(IOException e){e.printStackTrace();}
Maybe this method can be used for quick solution.
public class TestUtility
{
public static File getInternalResource(String relativePath)
{
File resourceFile = null;
URL location = TestUtility.class.getProtectionDomain().getCodeSource().getLocation();
String codeLocation = location.toString();
try{
if (codeLocation.endsWith(".jar"){
//Call from jar
Path path = Paths.get(location.toURI()).resolve("../classes/" + relativePath).normalize();
resourceFile = path.toFile();
}else{
//Call from IDE
resourceFile = new File(TestUtility.class.getClassLoader().getResource(relativePath).getPath());
}
}catch(URISyntaxException ex){
ex.printStackTrace();
}
return resourceFile;
}
}
When in a jar file, the resource is located absolutely in the package hierarchy (not file system hierarchy). So if you have class com.example.Sweet loading a resource named ./default.conf then the resource's name is specified as /com/example/default.conf.
But if it's in a jar then it's not a File ...
This Class function can get absolute file path by relative file path in .jar file.
public class Utility {
public static void main(String[] args) throws Exception {
Utility utility = new Utility();
String absolutePath = utility.getAbsolutePath("./absolute/path/to/file");
}
public String getAbsolutePath(String relativeFilePath) throws IOException {
URL url = this.getClass().getResource(relativeFilePath);
return url.getPath();
}
}
If target file is same directory with Utility.java, your input will be ./file.txt.
When you input only / on getAbsolutePath(), it returns /Users/user/PROJECT_NAME/target/classes/. This means you can select the file like this /com/example/file.txt.

Categories

Resources