This question already has answers here:
File inside jar is not visible for spring
(13 answers)
Closed 4 years ago.
Error :
java.io.FileNotFoundException: class path resource [xml/ruleSet.xml] cannot be resolved to absolute file path because it does not reside in the file system: jar:file:/app/target/******-0.0.1-SNAPSHOT.jar!/BOOT-INF/classes!/xml/ruleSet.xml
Code :
File ruleSet = new ClassPathResource("xml/ruleSet.xml").getFile();
pmdConfiguration.setReportFormat("text");
pmdConfiguration.setRuleSets(ruleSet.getAbsolutePath());
I need to insert the full file into the setRuleSets method, how will FileInputStream help me here?
FileInputStream ruleSet = new FileInputStream(ClassLoader.getSystemResource
("xml/ruleSet.xml").getPath());
Should I recreate a temp file by reading the fileinput stream and pass that file path to setRuleSets method?
The fundamental problem is that there is no path in the file system namespace for a resource in a JAR file. That is why ClassPathResource::getFile is throwing an exception, and it is also why URL::getPath.
There is an alternative. Use an InputStream, not a FileInputStream, and use the classloader API method for opening a resource as a stream.
Change:
FileInputStream ruleSet = new FileInputStream(ClassLoader.getSystemResource
("xml/ruleSet.xml").getPath());
to
InputStream ruleSet = ClassLoader.getSystemResourceAsStream("xml/ruleSet.xml");
In this case, this won't work because PMDConfiguration::setRuleSets doesn't take a stream argument.
However, the javadoc states:
public void setRuleSets(String ruleSets)
Set the command1 separated list of RuleSet URIs.
Since the getResource methods return a URL, you should be able to do this:
pmdConfiguration.setRuleSets(
ClassLoader.getSystemResource("xml/ruleSet.xml").toString();
UPDATE
If getSystemResource or getSystemResourceAsStream fails, then either the resource does not exist (in the JARs, etc on the runtime classpath), the path is incorrect, or you should be using getResource or getResourceAsStream.
1 - The word "command" is a typo. It should be "comma".
Ok So I figured out what to do here,
We already have input stream, thus I converted input stream to a temp file, and used that file.getPath.
ClassLoader classLoader = this.getClass().getClassLoader();
InputStream resourceAsStream = classLoader.getResourceAsStream("xml/ruleSet.xml");
String ruleSetFilePath = "";
if(resourceAsStream != null){
File file = stream2file(resourceAsStream);
ruleSetFilePath = file.getPath();
}
pmdConfiguration.setRuleSets(ruleSetFilePath);
public static File stream2file (InputStream in) throws IOException {
final File tempFile = File.createTempFile("ruleSet", ".xml");
tempFile.deleteOnExit();
try (FileOutputStream out = new FileOutputStream(tempFile)) {
IOUtils.copy(in, out);
}
return tempFile;
}
Related
This question already has answers here:
How to solve the java.nio.file.NoSuchFileException?
(6 answers)
Closed 9 months ago.
I try to read a file from the resources and it tells me
java.io.FileNotFoundException: file:/home/simon/IdeaProjects/KTMBlockChain/build/resources/main/certificate_template.docx (No such file or directory)
Note that the file is blue and clickable. When I click on it it also opens the file so it definietly exists in the place expected.
Code:
InputStream in = null;
try {
File file = new File(this.getClass().getClassLoader().getResource("certificate_template.docx").toString());
in = new FileInputStream(file);
IXDocReport report = XDocReportRegistry.getRegistry().
loadReport(in, TemplateEngineKind.Freemarker);
Options options = Options.getTo(ConverterTypeTo.PDF).via(ConverterTypeVia.ODFDOM);
IContext ctx = report.createContext();
ctx.put("re_wo", pdfData.getReifen());
/*ctx.put("to", invoice.getTo());
ctx.put("sender", invoice.getInvoicer());
FieldsMetadata metadata = report.createFieldsMetadata();
ctx.put("r", invoice.getInvoiceRows());*/
report.convert(ctx, options, new FileOutputStream("result.pdf"));
I dont know what to do anymore...
EDIT 1: Changed code, still not working, another error code but same problem
There are
Disk files, class File;
Resource files (read-only), on the class path, possibly packed in a jar or war.
So here is you should use a resource, and Path is a generalisation of File, and all other kind of URL paths. This caused the error.
URL url = getClass().getClassLoader().getResource("certificate_template.docx");
Path path = Paths.get(url.toURI());
List<String> x = Files.readAllLines(path); // Reading a UTF-8 text.
But docx is not text, but a binary format (actually a zip format).
You either need to use a library or just handle the file as-is, like let the operating system open it.
You could use Files.readAllBytes(); reading UTF-8 will probably cause an error as the bytes are not in UTF-8 format.
After edit of question:
in = getClass().getClassLoader().getResourceAsStream("certificate_template.docx");
So I have a small resource loader for stuff that I need. The jar packages the resources but when I build the maven project, and all the dependencies work and resources folder is marked as resources, my images and scripts wont load.
Here is the code I am using:
...
public class ResourceLoader
{
public static ImageIcon getImageIconResource(String fileName) {
ClassLoader classLoader = ClassLoader.getSystemClassLoader();
File file = new File(classLoader.getResource("img/" + fileName).getFile());
return new ImageIcon(file.getPath());
}
public static File getScriptResource(String fileName) {
ClassLoader classLoader = ClassLoader.getSystemClassLoader();
return new File(classLoader.getResource("scripts/" + fileName).getFile());
}
}
The problem is not with maven itself. When you call
File.getPath
on File from the resource it points to a File, that is actually inside of your application archive. For most applications, this pose a problem because you cannot read file without extracting the archive. To correctly use resource file, you have to work with File, or you can call
ClassLoader.getResourcesAsStream
To adress ImageIcon
public static ImageIcon getImageIconResource(String fileName) {
ClassLoader classLoader = ClassLoader.getSystemClassLoader();
InputStream is = classLoader.getResourceAsStream("img/" + fileName);
Image image = ImageIO.read(is);
return new ImageIcon(image);
}
As for your getScriptResource method geting File object should work. But that depends, on how you will later use it. As I think you will need to read it anyway at some point I suggest using input stream as well.
public static InpoutStream getScriptResource(String fileName) {
ClassLoader classLoader = ClassLoader.getSystemClassLoader();
InputStream is = classLoader.getResourceAsStream("scripts/" + fileName);
return is;
}
Then, you can read the InputStream using many options that suits your need. For example, you can take a look at Apache Commons' IoUtils or handle it using ReaderApi
EDIT:
Because you have clarified how you will use your file I can see where is the problem with your scripts. You are starting another process outside of your application. In the first CLI param of python3, you are providing path to the file. As I wrote earlier - this is the problem, because python3 cannot read file inside of .jar file. First of all, I would have questioned your architecture. Do you really need to have script inside of .jar?
Anyway, one possible workaround may be storing contents of a script File in temporaryFile.
File tempFile = File.createTempFile("prefix-", "-suffix");
// e.g.: File tempFile = File.createTempFile("MyAppName-", ".tmp");
tempFile.deleteOnExit();
//get your script and prepare OutputStream to tempFile
// Try with resources, because you want to close your streams
try (InputStream is = ResourceLoader.getScriptResource(scriptName);
FileOutputStream out = new FileOutputStream(tempFile)) {
//NOTE: You can use any method to copy InputStream to OutputStream.
//Here I have used Apache IO Utils
IOUtils.copy(is, out);
}
boolean success = executePythonScriptWithArgs(tempFile, args);
I am getting an NPE at the point of getting path of a File (an sh file in assets folder).
I have tried to read about NPE i detail from the following thread, but this actually could not solve my problem.
What is a NullPointerException, and how do I fix it?
Following is my code snippet:
File absPathofBash;
url = ClassLoader.class.getResource("assets/forbackingup.sh");
absPathofBash = new File(url.getPath());
Later I'm using it in a ProcessBuilder, as
ProcessBuilder pb = new ProcessBuilder(url.getPath(), param2, param3)
I've also tried getting the absolute path directly, like
absPathofBash = new File("assets/forbackingup.sh").getAbsolutePath();
Using the latter way, I am able to process it, but if I create a jar then the file cannot be found. (although the Jar contains the file within the respective folder assets)
I would be thankful if anyone can help me on that.
Once you have packaged your code as a jar, you can not load files that are inside the jar using file path, instead they are class resources and you have to use this to load:
this.getClass().getClassLoader().getResource("assets/forbackingup.sh");
This way you load assets/forbackingup.sh as an absolute path inside your jar. you also can use this.getClass().getResource() but this way the path must be relative to this class path inside jar.
getResource method gives you an URL, if you want to get directly an InputStream you can use getResourceAsStream
Hope it helps!
Since the file itself is in the jar file, you could try using:
InputStream is = this.getClass().getClassLoader().getResourceAsStream(fileNameFromJar);
In case of jar file , classloader will return URL different than that of when the target file is not embedded inside jar. Refer to answer on link which should help u :
How to use ClassLoader.getResources() in jar file
I got it done by creating a temp file. Though it's not difficult, yet I'm posting the code patch here:
InputStream stream = MyClass.class.getClassLoader().
getResourceAsStream("assets/forbackingup.sh");
File temp = File.createTempFile("forbackingup", ".sh");
OutputStream outputStream =
new FileOutputStream(temp);
int read = 0;
byte[] bytes = new byte[1024];
while ((read = stream.read(bytes)) != -1) {
outputStream.write(bytes, 0, read);
outputStream.close();
}
Now, we have this temp file here which we can pipe to the ProcessBuilder like,
String _filePath=temp.getPath();
ProcessBuilder pb = new ProcessBuilder(url.getPath(), param2, param3)
Thank you everyone for your considerations.
You can use Path class like :
Path path = Paths.get("data/test-write.txt");
if(!Files.exists(path)){
// can handle null pointer exception
}
I need to be able to access a file stored in a compiled jar file. I have figured out how to add the file to the project, but how would I reference it in the code? How might I copy a file from the jar file to a location on the user's hard drive? I know there are dozens of ways to access a file (FileInputStream, FileReader, ect.), but I don't know how to look inside itself.
You could use something like this:
InputStream is = this.getClass().getClassLoader().getResourceAsStream(fileFromJarFile);
If foo.txt was in the root of your JAR file, you'd use:
InputStream is = this.getClass().getClassLoader().getResourceAsStream("foo.txt");
assumes the class is in the same JAR file as the resource, I believe.
You can use getResource() to obtain a URL for a file on the classpath, or getResourceAsStream() to get an InputStream instead.
For example:
BufferedReader reader = new BufferedReader(new InputStreamReader(
this.getClass().getResourceAsStream("foo.txt")));
You could read the contents of a JAR file using the JarFile class.
Here's an example of how you could get a specific file from a JAR file and extract it:
JarFile jar = new JarFile("foo.jar");
String file = "file.txt";
JarEntry entry = jar.getEntry(file);
InputStream input = jar.getInputStream(entry);
OutputStream output = new FileOutputStream(file);
try {
byte[] buffer = new byte[input.available()];
for (int i = 0; i != -1; i = input.read(buffer)) {
output.write(buffer, 0, i);
}
} finally {
jar.close();
input.close();
output.close();
}
Just wanted to add that if we want to access file inside Jar that is located at the following path(only examples as resources loading is OS independent):
Windows:
c:\your-jar-file.jar\dir1\dir2\dir3\foo.txt
Linux:
/home/your-jar-file.jar/dir1/dir2/dir3/foo.txt
Will need to use following code(pay attention that there is NO "/"(forward-slash) character in the beginning of the path):
InputStream is = this.getClass().getClassLoader().getResourceAsStream("dir1/dir2/dir3/foo.txt");
Look at the JarFile class. Everything you need to get the InputStream of a specific entry in the jar file is there.
I have a project with 2 packages:
tkorg.idrs.core.searchengines
tkorg.idrs.core.searchengines
In package (2) I have a text file ListStopWords.txt, in package (1) I have a class FileLoadder. Here is code in FileLoader:
File file = new File("properties\\files\\ListStopWords.txt");
But I have this error:
The system cannot find the path specified
Can you give a solution to fix it?
If it's already in the classpath, then just obtain it from the classpath instead of from the disk file system. Don't fiddle with relative paths in java.io.File. They are dependent on the current working directory over which you have totally no control from inside the Java code.
Assuming that ListStopWords.txt is in the same package as your FileLoader class, then do:
URL url = getClass().getResource("ListStopWords.txt");
File file = new File(url.getPath());
Or if all you're ultimately after is actually an InputStream of it:
InputStream input = getClass().getResourceAsStream("ListStopWords.txt");
This is certainly preferred over creating a new File() because the url may not necessarily represent a disk file system path, but it could also represent virtual file system path (which may happen when the JAR is expanded into memory instead of into a temp folder on disk file system) or even a network path which are both not per definition digestable by File constructor.
If the file is -as the package name hints- is actually a fullworthy properties file (containing key=value lines) with just the "wrong" extension, then you could feed the InputStream immediately to the load() method.
Properties properties = new Properties();
properties.load(getClass().getResourceAsStream("ListStopWords.txt"));
Note: when you're trying to access it from inside static context, then use FileLoader.class (or whatever YourClass.class) instead of getClass() in above examples.
The relative path works in Java using the . specifier.
. means same folder as the currently running context.
.. means the parent folder of the currently running context.
So the question is how do you know the path where the Java is currently looking?
Do a small experiment
File directory = new File("./");
System.out.println(directory.getAbsolutePath());
Observe the output, you will come to know the current directory where Java is looking. From there, simply use the ./ specifier to locate your file.
For example if the output is
G:\JAVA8Ws\MyProject\content.
and your file is present in the folder "MyProject" simply use
File resourceFile = new File("../myFile.txt");
Hope this helps.
The following line can be used if we want to specify the relative path of the file.
File file = new File("./properties/files/ListStopWords.txt");
InputStream in = FileLoader.class.getResourceAsStream("<relative path from this class to the file to be read>");
try {
BufferedReader reader = new BufferedReader(new InputStreamReader(in));
String line = null;
while ((line = reader.readLine()) != null) {
System.out.println(line);
}
} catch (Exception e) {
e.printStackTrace();
}
try .\properties\files\ListStopWords.txt
I could have commented but I have less rep for that.
Samrat's answer did the job for me. It's better to see the current directory path through the following code.
File directory = new File("./");
System.out.println(directory.getAbsolutePath());
I simply used it to rectify an issue I was facing in my project. Be sure to use ./ to back to the parent directory of the current directory.
./test/conf/appProperties/keystore
While the answer provided by BalusC works for this case, it will break when the file path contains spaces because in a URL, these are being converted to %20 which is not a valid file name. If you construct the File object using a URI rather than a String, whitespaces will be handled correctly:
URL url = getClass().getResource("ListStopWords.txt");
File file = new File(url.toURI());
Assuming you want to read from resources directory in FileSystem class.
String file = "dummy.txt";
var path = Paths.get("src/com/company/fs/resources/", file);
System.out.println(path);
System.out.println(Files.readString(path));
Note: Leading . is not needed.
I wanted to parse 'command.json' inside src/main//js/Simulator.java. For that I copied json file in src folder and gave the absolute path like this :
Object obj = parser.parse(new FileReader("./src/command.json"));
For me actually the problem is the File object's class path is from <project folder path> or ./src, so use File file = new File("./src/xxx.txt"); solved my problem
For me it worked with -
String token = "";
File fileName = new File("filename.txt").getAbsoluteFile();
Scanner inFile = null;
try {
inFile = new Scanner(fileName);
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
while( inFile.hasNext() )
{
String temp = inFile.next( );
token = token + temp;
}
inFile.close();
System.out.println("file contents" +token);
If text file is not being read, try using a more closer absolute path (if you wish
you could use complete absolute path,) like this:
FileInputStream fin=new FileInputStream("\\Dash\\src\\RS\\Test.txt");
assume that the absolute path is:
C:\\Folder1\\Folder2\\Dash\\src\\RS\\Test.txt
String basePath = new File("myFile.txt").getAbsolutePath();
this basepath you can use as the correct path of your file
if you want to load property file from resources folder which is available inside src folder, use this
String resourceFile = "resources/db.properties";
InputStream resourceStream = ClassLoader.getSystemClassLoader().getResourceAsStream(resourceFile);
Properties p=new Properties();
p.load(resourceStream);
System.out.println(p.getProperty("db"));
db.properties files contains key and value db=sybase
If you are trying to call getClass() from Static method or static block, the you can do the following way.
You can call getClass() on the Properties object you are loading into.
public static Properties pathProperties = null;
static {
pathProperties = new Properties();
String pathPropertiesFile = "/file.xml";
// Now go for getClass() method
InputStream paths = pathProperties.getClass().getResourceAsStream(pathPropertiesFile);
}