getResourceAsStream fails under new environment? - java

Hallo,
i have following line of code:
InputStream passoloExportFileInputStream = getClass().getClassLoader().getResourceAsStream("/com/thinkplexx/lang/de/general.xml");
and i know that jar with com/thinkplexx/lang/de/general.xml is in classpath.
It worked under "previous environment", which is maven2 build.
Now, i evaluate maven3 and it doesn't work! I know, that if i change the code to be:
InputStream passoloExportFileInputStream = getClass().getClassLoader().getResourceAsStream("com/thinkplexx/lang/de/general.xml");
it works great (i just removed the first slash from the resource path).
Btw, i use Linux. First slash in path normally means "from the root directory", so if this logic is sound for java resource loading as well, first example should never have worked!?
Questions: is something wrong with the first code sample, i.e. with /com/ and not com/? Is it just bad code or it means something different?
thank you!

It depends on how you are getting the resource. When you use a ClassLoader as in:
InputStream stream= getClass().getClassLoader().getResourceAsStream("/com/thinkplexx/lang/de/general.xml");
The leading '/' is meaningless. So, the correct form is "com/thinkplexx/lang/de/general.xml".
If, instead you use a 'Class', as in:
InputStream stream= getClass().getResourceAsStream("/com/thinkplexx/lang/de/general.xml");
You get a different behavior. The Class.getResourceAsStream will consider classes without a leading '.' to be relative to the package containing the class. Resources specified with a leading '.' are absolute, or resolved relative to the root of the jar.
So, if this is a reference to com.example.SomeThing, then the expected behavior is:
getClass().getResourceAsStream("/a/b/c.xml") ==> a/b/c.xml
getClass().getResourceAsStream("a/b/c.xml") ==> com/example/a/b/c.xml
getClass().getClassLoader().getResourceAsStream("a/b/c.xml") ==> a/b/c.xml
getClass().getClassLoader().getResourceAsStream("/a/b/c.xml") ==> Incorrect
Maven2 was being lax and allowing the last form.

Related

What exactly does it mean to "resolve" a path?

I've now read numerous articles on the use of Java somePath.resolve( someOtherPath ) but I can't find a precise definition, with helpful examples, of what exactly "resolving" a Path means. Everyone seems to assume you know.
Can someone define it non-circularly? Or point me to a (non-circular) explainer?
The answer to this is defined in the documentation, which does a great job of indicating what the method does.
Converts a given path string to a Path and resolves it against this Path in exactly the manner specified by the resolve method. For example, suppose that the name separator is "/" and a path represents "foo/bar", then invoking this method with the path string "gus" will result in the Path "foo/bar/gus".
In other words, if the path C:/Program Files/Foo/ is the current Path and Bar exists in Foo, you could do the following:
Path parent = Paths.get("C:", "Program Files", "Foo");
Path child = parent.resolve("Bar");
Jason's answer is complete, but on the off chance you're looking for an even simpler answer/example..
I would say the "resolve" method that you specificaly referred to (which starts at somePath) starts at a certain Path, somePath, and then tells you what would happen if you choose to go to someOtherPath but specifically starting at somePath.
So if you had a directory structure on a PC, for example, like this:
C:
- FolderA
- Folder1
- FolderB
- Folder1
If you resolved someOtherPath as "Folder1", then it would depend where you started...
If your somePath was "/FolderA" then you'd end up at "C:/FolderA/Folder1"
If your somePath was "/FolderB" then you'd end up at "C:/FolderB/Folder1"
If your somePath was "/" (the root), then you'd have an invalid path...

reading a text file from within a Jar on a remote device

Having researched this issue extensively here & elsewhere, without finding a working solution, I thought I'd ask...
I have a jar file (deployed on a RaspberryPi), with an internal structure like this:
myApp
MyClass
....
textFiles
foo.txt
....
I need 'MyClass' to read 'foo.txt'.
the general advice here & elsewhere is to use something like the following:
InputStream in = getClass().getResourceAsStream("../textFiles/foo.txt");
BufferedReader reader = new BufferedReader(new InputStreamReader(in));
I have also read that the path to use (as the param for getResourceAsStream()) is the path to the target file, relative to the location of the class reading the file.(..?)
However, regardless of the path I use, I cannot get the above 2 lines to work. I always get an NPE thrown by the 2nd line.
I'm assuming that the NPE indicates that 'in' is null because 'foo.txt' has not been found.
any advice leading to a successful resolution, gratefully received.
cheers
Paul
Try removing the .. from the path, as per documentation:
If the name begins with a '/' ('\u002f'), then the absolute name of the resource is the portion of the name following the '/'.
Otherwise, the absolute name is of the following form:
modified_package_name/name
Where the modified_package_name is the package name of this object with '/' substituted for '.' ('\u002e').
So my immediate problem has been solved, but not to my satisfaction.
I relocated the contents of 'textFiles' (in the Jar), so all the text files were in the Jar's root. I then successfully managed to find & load the file using:
InputStream in = getClass().getResourceAsStream("/foo.txt");
However, I still don't undserstand why this worked. I don't see why "/textFiles/foo.txt" didn't work, when the files were in that subdir, off the Jar's root...?
Anyway...I have a new problem now, which I think is hardware related....it takes about 40 seconds to read the files!! I think I blame the old SD card in my Raspberry Pi.
But that's a problem for another day!
Thanks for your input.

moving File leads to file with path separator "/" in filename

I try to move a file from one directory to another.
I do this with
File fileToMove = new File("/Users/kai-dj/separator_problem/from/file_to_move.file");
File destDir = new File("/Users/kai-dj/separator_problem/to");
if (fileToMove.exists() && destDir.isDirectory()) {
fileToMove.renameTo(new File(destDir.getAbsolutePath()+File.pathSeparator+fileToMove.getName()));
}
I'd expect to find file_to_move.file in folder /Users/kai-dj/separator_problem/to after execution, but I get a file named to/file_to_move.file placed in the parent folder /Users/kai-dj/separator_problem. At least that's what Finder shows.
As I thought: "File names mustn't contain path separator characters, this can't be true.", I also checked what ls would output in terminal:
mac-book:separator_problem kai-dj$ ls
from to:file_to_move.file
to
OK – seems no /in file name. Very strange nontheless.
Why does Finder show it as file name containing /?
Why does Java rename the file to <dirname>:<filename> – especially even when I used File.pathSeparator, not / and certainly not :?
I also tried with Files.move – same result.
EDIT: Solved, but I'd still love to know, why Finder shows : as / ^^
As mentioned in the comment above, the correct member to use is called File.separator.
Also, you can avoid using File.separator in general, and use Paths instead:
System.out.println(Paths.get("/Users/kai-dj/separator_problem/to", fileToMove.getName()).toAbsolutePath());

adding image in java swing [duplicate]

I need to get a resource image file in a java project. What I'm doing is:
URL url = TestGameTable.class.getClass().
getClassLoader().getResource("unibo.lsb.res/dice.jpg");
The directory structure is the following:
unibo/
lsb/
res/
dice.jpg
test/
..../ /* other packages */
The fact is that I always get as the file doesn't exist. I have tried many different paths, but I couldn't solve the issue.
Any hint?
TestGameTable.class.getResource("/unibo/lsb/res/dice.jpg");
leading slash to denote the root of the classpath
slashes instead of dots in the path
you can call getResource() directly on the class.
Instead of explicitly writing the class name you could use
this.getClass().getResource("/unibo/lsb/res/dice.jpg");
if you are calling from static method, use :
TestGameTable.class.getClassLoader().getResource("dice.jpg");
One thing to keep in mind is that the relevant path here is the path relative to the file system location of your class... in your case TestGameTable.class. It is not related to the location of the TestGameTable.java file.
I left a more detailed answer here... where is resource actually located

Program not running from expected directory?

I am working on a web-based program, using Java. I am not sure exactly how to phrase this, but I expect the program to be running from within the c:/Resin/webapps/apps directory. However, when I reference a file in the program like this: "../files/randomfile.pdf", it cannot find that file. It works when I reference it like this: "c:/Resin/webapps/files/randomfile.pdf". How to I change the "running location"? (And what is the technical term for this?)
try {
Document iTextDoc = new Document(PageSize.LETTER, 27, 27, 35, 18);
HttpServletResponse res = (HttpServletResponse) pageContext.getResponse();
res.setContentType("application/vnd.ms-word");
res.setHeader("Content-Disposition", "attachment; filename=" + fileName + ".rtf;");
RtfWriter2 rtfWriter = RtfWriter2.getInstance(iTextDoc, res.getOutputStream());
iTextDoc.open();
iTextDoc.add(new Paragraph ("Testing RTF Letterhead with Logo"));
// Use full classname to avoid ambiguity with java.awt.Image
com.lowagie.text.Image logoImg = com.lowagie.text.Image.getInstance("../files/someimage.jpg");
logoImg.setAlignment(Image.RIGHT | Image.TEXTWRAP);
iTextDoc.add(logoImg);
iTextDoc.add(new Paragraph ("Put other information about organization beneath logo"));
iTextDoc.close();
}
I get the following error with the resulting file: Adobe Reader could not open 'someFile.pdf' because it is either not a supported file type or because the file has been damaged (for example, it was sent as an email attachment and wasn't correctly decoded).
However, if I change the getInstance command to this:
com.lowagie.text.Image logoImg = com.lowagie.text.Image.getInstance("webapps/files/someimage.jpg");
it works. So my guess is that the working directory (thanks for the term) needs to be set somewhere. I am using Resin -- any idea where I should be setting this?
Thanks!
You are probably referring to the user.dir system property, which is read only. Relative paths use this as the root folder.
In a java program you can't change the running location.
First you should find out where your program is running. You can do this by calling
System.out.println( new File( "." ).getAbsolutePath() );
Now you can specify your paths relative to this directory.
From the java.io.File doc
By default the classes in the java.io package always resolve relative pathnames against the current user directory. This directory is named by the system property user.dir, and is typically the directory in which the Java virtual machine was invoked.
Broadly speaking, you should not rely on the current directory for locating files. Use full (absolute) paths, if possible (but without harcoding it in you application, of course). if the file is inside a webapp tree (or just inside the classpath), you might want to take a look at findResource() and related methods.

Categories

Resources