I'm trying to incorporate a css file to my JavaFX appllication, by the following snippet:
public void loadExternalCSS() {
System.out.println("CLASSPATH: "+System.getProperty("java.class.path"));
try{
skinCSS = getClass().getResource("css/default_skin.css").toExternalForm();
}
catch(Exception e){
System.err.println("Exception: " + e);
e.printStackTrace(System.err);
}
}
Which yields, at runtime:
java.lang.NullPointerException
at
robotikosanomologitos.RobotikosAnomologitos.loadExternalCSS(RobotikosAnomologitos.java:529)
at robotikosanomologitos.RobotikosAnomologitos.start(RobotikosAnomologitos.java:491)
at com.sun.javafx.application.LauncherImpl.lambda$launchApplication1$162(LauncherImpl.java:863)
at com.sun.javafx.application.PlatformImpl.lambda$runAndWait$175(PlatformImpl.java:326)
at com.sun.javafx.application.PlatformImpl.lambda$null$173(PlatformImpl.java:295)
at java.security.AccessController.doPrivileged(Native Method)
at com.sun.javafx.application.PlatformImpl.lambda$runLater$174(PlatformImpl.java:294)
at com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:95)
at com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
at com.sun.glass.ui.win.WinApplication.lambda$null$148(WinApplication.java:191)
at java.lang.Thread.run(Thread.java:745)
The weird thing is that a few lines above this function, I have a small function that reads from a properties file.
public void readPropertiesFile() {
Properties props = new Properties();
InputStream is;
try {
File f = new File("properties");
is = new FileInputStream(f);
}
/* etcetera */
}
This works like a charm. The properties file is located at the root of the project directory, C:\~my_projects_folder~\RobotikosAnomologitos
After searching around for a solution, I saw that getClass().getResource() attempts to find a resource in the classpath. I tried printing the classpath at every run, and I get:
RobotikosAnomologitos\dist\run125323585\RobotikosAnomologitos.jar which is logical enough.
After looking inside this temporary folder while running the program, though, I can find no css folder nor css file.
But the file is indeed located in my working project directory, under RobotikosAnomologitos\css\default_skin.css. For some reason it doesn't make it in the classpath at runtime, causing getResource() to return null when looking for it.
Any ideas on how to include it?
EDIT: I forgot to mention that I have also placed css/default_skin.css under the src package, and shows up in Netbeans' package tree (src/css/default_skin.css).
In the same way, I have some graphics that are located under src/graphics/ which get loaded fine by getClass().getResourceAsStream(). Which also bafflesss me as to why the css file can't be found. Maybe it doesn't get compiled in the jar?
If you call getResource() for a class and do not prepend a /, the path is considered to be relative to the package of the class.
If you've properly added the resources to the classpath, this should work:
skinCSS = getClass().getResource("/css/default_skin.css").toExternalForm();
You need to add css folder in classpath if you want retrieve using getClass().getResource("css/default_skin.css").toExternalForm();
Check if you are not using binary encode of CSS files (see Project Properties>Packaging). If you are using, the mentioned file extension should be ".bss".
Related
Code:
import java.io.*;
import java.util.Scanner;
public class Driver {
private int colorStrength;
private String color;
public static void main(String[] args) throws IOException {
String line, file = "strength.txt";
File openFile = new File(file);
Scanner inFile = new Scanner(openFile);
while (inFile.hasNext()) {
line = inFile.nextLine();
System.out.println(line);
}
inFile.close();
}
}
This is a small part of a program I am writing for a class (the two private attributes have yet to be used I know) but when I try to run this with the strength.txt file I receive the following errors:
Exception:
Exception in thread "main" java.io.FileNotFoundException: strength.txt (The system cannot find the file specified)
at java.io.FileInputStream.open(Native Method)
at java.io.FileInputStream.<init>(Unknown Source)
at java.util.Scanner.<init>(Unknown Source)
at Driver.main(Driver.java:14)
If anyone with Eclipse could help me figure this out it would be much appreciated!
You've used a relative file path which is relative to your project execution.
If you'd like to do it that way, simply put the strength.txt file in the base directory of your project. Like so:
Alternatively, you could reference the absolute file path on your system. For example, use:
Windows:
C:/dev/myproject/strength.txt
Mac/Unix:
/Users/username/dev/strength.txt
(or whatever the full path may be) instead.
Do this
System.out.println(openFile.getAbsolutePath());
It will show you where JVM expects to find the file and whether it is the folder you expect as well, Accordingly place the file or give the exact location
Use this to see what file path the system is using to reach the relative path
System.out.print(System.getProperty("user.dir"));
Then make sure that the relative path immediately follows this path.
You can also turn that into a string by doing
String filePath = System.getProperty("user.dir");
and then you can just add that to the beginning of the filepath like so,
ImageIcon imageIconRefVar = new ImageIcon(filePath + "/imagepathname");
I found this solved the issue for me when I used it in the path (which seemed odd since that should be the location it is in, but it worked)
You've used a relative file path which is relative to your project execution.
If this works for you, you can change the execution directory from the project root to the binary directory by:
"Run" -> "Run configurations"
In the "Arguments" tab, find "working directory" settings.
Switch from "Default" to "Other".
Click the "Workspace" button and select the project in pop-up window then click "OK"; this will bring you something like $(workspace_loc:proj-1).
Append "/bin" to the end of it; save the configuration.
I need this instead of simply putting files in project root directory when I am doing assignment and the professor requires specific file hierarchy; in addition, this is more portable than absolute path.
Inside the base directory create a folder, name it "res". Place your file inside "res" folder.
use String file = ".\\res\\strength.txt"; to reference the location of your file.
You should use a resource folder to store all the files you use in your program (a good practice).
And make a refrence of that file from your root directory. So the file is present within the package.
I have a javafx project, which contains multiple paths for images and text files :
private Image imgMan = new Image(getClass().getResource("../man.gif").toExternalForm());
FileHelper.resetScores("./bin/application/MAP/BestScores.txt");
...
When i launch from eclipse, it work normally, and access to images and files without any problem.
But when i try to export my project to a jar file, it export correctly, but it don't launch !
I try to launch it from cmd, the trace of stack said that he don't know the paths...
Caused by: java.lang.NullPointerException
at application.Client.(Client.java:31)
(line 31 in my code refer to the first line of code given in the question)
I try to create a resource folder and put all files into it, but no result.
So what is the best way to make it ?
where must i create the resource folder ?
and how to access the files into it from the code ?
Thank you
There are several thing you should check:
verify the path in your jar against the class you are looking. Your image must be there.
verify you have successfully loaded a resource because using it, eg: check if getResource returns null.
For the first point, it depends on how you build your jar:
Eclipse will by default copy class file and resources to bin unless you use m2e. If you use the Extract runnable JAR (from File > Export menu), it may ignore some resources.
If you use Maven then your images must be in src/main/resources by default.
For the second point, you should use a method that should check the resource exists before delegating to Image. While it won't change your core problem, you would have a less subtile error:
static javafx.scene.image.Image loadImage(Class<?> source, String path) {
final InputStream is = source.getResourceAsStream(path);
if (null == is) {
throw new IllegalStateException("Could not load image from " + source + " path: " + path);
}
try (is) { // Java 9 -> you may want to use InputStream is2 = is
return new javafx.scene.image.Image(is); // use is2 for Java < 9
}
}
You should also try with an absolute path (from the root of the jar, or your src/main/resources if you use maven):
Image image = loadImage(this.getClass(), "/images/man.gif");
I have a file named "word.txt".
It is in the same directory as my java file.
But when I try to access it in the following code this file not found error occurs:
Exception in thread "main" java.io.FileNotFoundException: word.txt
(The system cannot find the file specified)
at java.io.FileInputStream.open(Native Method)
at java.io.FileInputStream.<init>(Unknown Source)
at java.util.Scanner.<init>(Unknown Source)
at Hangman1.main(Hangman1.java:6)
Here's my code:
import java.io.File;
import java.util.*;
public class Hangman1 {
public static void main(String[] args) throws Exception {
Scanner input = new Scanner(new File("word.txt"));
String in = "";
in = input.nextLine();
}
}
Put the word.txt directly as a child of the project root folder and a peer of src
Project_Root
src
word.txt
Disclaimer: I'd like to explain why this works for this particular case and why it may not work for others.
Why it works:
When you use File or any of the other FileXxx variants, you are looking for a file on the file system relative to the "working directory". The working directory, can be described as this:
When you run from the command line
C:\EclipseWorkspace\ProjectRoot\bin > java com.mypackage.Hangman1
the working directory is C:\EclipseWorkspace\ProjectRoot\bin. With your IDE (at least all the ones I've worked with), the working directory is the ProjectRoot. So when the file is in the ProjectRoot, then using just the file name as the relative path is valid, because it is at the root of the working directory.
Similarly, if this was your project structure ProjectRoot\src\word.txt, then the path "src/word.txt" would be valid.
Why it May not Work
For one, the working directory could always change. For instance, running the code from the command line like in the example above, the working directory is the bin. So in this case it will fail, as there is not bin\word.txt
Secondly, if you were to export this project into a jar, and the file was configured to be included in the jar, it would also fail, as the path will no longer be valid either.
That being said, you need to determine if the file is to be an embedded-resource (or just "resource" - terms which sometimes I'll use interchangeably). If so, then you will want to build the file into the classpath, and access it via an URL. First thing you would need to do (in this particular) case is make sure that the file get built into the classpath. With the file in the project root, you must configure the build to include the file. But if you put the file in the src or in some directory below, then the default build should put it into the class path.
You can access classpath resource in a number of ways. You can make use of the Class class, which has getResourceXxx method, from which you use to obtain classpath resources.
For example, if you changed your project structure to ProjectRoot\src\resources\word.txt, you could use this:
InputStream is = Hangman1.class.getResourceAsStream("/resources/word.txt");
BufferedReader reader = new BufferedReader(new InputStreamReader(is));
getResourceAsStream returns an InputStream, but obtains an URL under the hood. Alternatively, you could get an URL if that's what you need. getResource() will return an URL
For Maven users, where the directory structure is like src/main/resources, the contents of the resources folder is put at the root of the classpath. So if you have a file in there, then you would only use getResourceAsStream("/thefile.txt")
Relative paths can be used, but they can be tricky. The best solution is to know where your files are being saved, that is, print the folder:
import java.io.File;
import java.util.*;
public class Hangman1 {
public static void main(String[] args) throws Exception {
File myFile = new File("word.txt");
System.out.println("Attempting to read from file in: "+myFile.getCanonicalPath());
Scanner input = new Scanner(myFile);
String in = "";
in = input.nextLine();
}
}
This code should print the folder where it is looking for. Place the file there and you'll be good to go.
Your file should directly be under the project folder, and not inside any other sub-folder.
If the folder of your project is named for e.g. AProject, it should be in the same place as your src folder.
Aproject
src
word.txt
Try to create a file using the code, so you will get to know the path of the file where the system create
File test=new File("check.txt");
if (test.createNewFile()) {
System.out.println("File created: " + test.getName());
}
I was reading path from a properties file and didn't mention there was a space in the end.
Make sure you don't have one.
Make sure when you create a txt file you don't type in the name "name.txt", just type in "name". If you type "name.txt" Eclipse will see it as "name.txt.txt". This solved it for me. Also save the file in the src folder, not the folder were the .java resides, one folder up.
I have the same problem, but you know why? because I didn't put .txt in the end of my File and so it was File not a textFile, you shoud do just two things:
Put your Text File in the Root Directory (e.x if you have a project called HelloWorld, just right-click on the HelloWorld file in the package Directory and create File
Save as that File with any name that you want but with a .txt in the end of that
I guess your problem is solved, but I write it to other peoples know that.
Thanks.
i think it always boils to the classpath. having said that if you run from the same folder where your .class is then change Scanner input = new Scanner(new File("word.txt")); to Scanner input = new Scanner(new File("./word.txt")); that should work
The question started as - maven does not reach into jar for a folder bundle correctly, when running tests. It does work currectly when running some main() though.
The stack trace for running test (while building) looked like this:
Caused by: java.util.MissingResourceException: Can't find Not found profile: file:\C:\Users\Simon\.m2\repository\ario\TextProcessing\1.0.4-SNAPSHOT\TextProcessing-1.0.4-SNAPSHOT.jar!\lang bundle
at java.util.logging.Logger.setupResourceInfo(Logger.java:1942)
at java.util.logging.Logger.<init>(Logger.java:380)
at java.util.logging.LogManager.demandLogger(LogManager.java:554)
at java.util.logging.Logger.demandLogger(Logger.java:455)
at java.util.logging.Logger.getLogger(Logger.java:553)
at cz.techniserv.ario.tagger.TagDetect.setLangPath(TagDetect.java:126)
at cz.techniserv.ario.tagger.TagDetect.<init>(TagDetect.java:58)
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:408)
at org.springframework.beans.BeanUtils.instantiateClass(BeanUtils.java:147)
... 86 more
I triple checked - the lang folder is within the jar.
When running a main() within the module however, it does not try to reach into jar withing m2 repository, but will take the lang folder from within the opened dependency project. So it does not try to reach into a jar, just takes the data from project folder. This runs correctly.
Apparently, the File() constructor is unable to reach for the resource in the jar.
The code, that tries to reach into the jar is within a constructor. It looks like this:
this.path = this.getClass().getResource("/" + aLanguageDirectoryName).getPath();
and than there is a File constructor which takes this path.
In case of running the app it resolves to the project path. When it runs tests it will resolve to the jar within the m2 repository and tries to reach within the path that is in the exception:
file:\C:\Users\Simon\.m2\repository\ario\TextProcessing\1.0.4-SNAPSHOT\TextProcessing-1.0.4-SNAPSHOT.jar!\lang
What would you do? Would you copy the resource "lang" folder on some temporary path and provide the library with this new non-within-jar temporary path, so that it can open with the File() constructor? Or do you see another better way?
Ok, so what we did is that the data are ad hoc extracted to classpath and accessed.
The problem with this solution is that if you delete the files after usage, than you will always extract and delete data with each run - when this happens with every spring initialization of running tests this can happen extreme amount of times and take a lot of time. Leaving the data there however means that if the path is not absolute and out of the project trunk folder, SCM will pick it up unless you ignore it and commit the data which is not satisfying. Also they get packed into the jar upon build since they are on classpath which is another drawback. Yes, you can ignore with SCM and configure maven to exclude the folder, however some developers will forget (one already did) to ignore with SCM and it was commited.
We consider extracting to an absolute path which would not be on classpath a bad practice - firstly because you have no control on what system the projects run on so you cannot guess very well the absolute path - also it does not look pretty to throw data around your computer for bad design.
So I guess the best thing would be to push everyone to place the data on some place on their discs and set an environment variable which would be the same for everyone. This makes the project less portable, requires more configuration, but removes formerly mentioned problems.
I did not come up with anything better.
In case anyone would want to do the same thing, here is our code:
CodeSource src = this.getClass().getProtectionDomain().getCodeSource();
if (src == null) {
return null;
}
URL jarURL = src.getLocation();
try (JarFile jar = new JarFile(jarURL.getPath());) {
Enumeration<JarEntry> enumEntries = jar.entries();
while (enumEntries.hasMoreElements()) {
JarEntry fileFromJar = (JarEntry) enumEntries.nextElement();
File toBeCreatedFileLocally = new File(NAME_FOR_TEMPORARY_FOLDER_TO_HOLD_LANG_DATA_FROM_JAR + File.separator + fileFromJar.getName());
if (fileFromJar.isDirectory()) {
continue;
}
if (fileFromJar.getName().contains(aLanguageDirectoryName)) {
toBeCreatedFileLocally.getParentFile().mkdirs();
try (InputStream is = jar.getInputStream(fileFromJar); // get the input stream
FileOutputStream fos = new FileOutputStream(toBeCreatedFileLocally)) {
while (is.available() > 0) { // write contents of 'is' to 'fos'
fos.write(is.read());
}
}
}
}
} catch (IOException ex) {
Logger.getLogger(TagDetect.class.getName()).log(Level.SEVERE, null, ex);
}
This code is actually a modification of a different answer here https://stackoverflow.com/a/1529707/1920149 (beware, that answer has a bug, check comments - they rejected my edit)
Hi i have exported my java project as executable jar file. inside my project I am accessing a Excel file containing some data. Now I am not able to access the Excel file when I am trying to access the file.
My project structure is:
Java_Project_Folder
- src_Folder
- resources_Folder(Containing excel file)
I am accessing the excel file like
FileInputStream file=new FileInputStream(new File(System.getProperty("user.dir")
+File.separator+"resources"+File.separator+"Excel.xlsx"));
I have tried accessing this file using getResourceAsStream like:
FileInputStream file=(FileInputStream) this.getClass().getResourceAsStream
("/resources/Excel.xlsx");
But i am getting in is null exception. whats wrong can anyone help?
I bet you have no package called resources in your project.
Trying to use Class.#getResourceAsStream is the way to go. But this method does not return a FileInputStream. It returns an InputStream wich is an interface.
You should be passing the absolute name of the resource
InputStream is = getClass().getResourceAsStream("my/pack/age/Excel.xlsx");
where the excel file is located in the directory
resources/my/pack/age
The first step is to include the excel file itself in your project. You can create a resources folder like you show, but to make sure this gets included in your jar, you add the resources folder in along with your source code files so that it gets built into the jar.
Then
InputStream excelContent = this.getClass().getResourceAsStream("/resources/Excel.xlsx");
should work. From one post at least, the leading forward slash may also mess things up if you use the ClassLoader.
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
ref: getResourceAsStream fails under new environment?
Also in eclipse you can set the resources folder as a source folder like this:
in the properties of your eclipse project, go to java build path, select sources, and check to see if all needed source fodlers are added (as source folders). If some are missing, just add them manually using add sources... button
ref: Java Resources Folder Error In Eclipse
I tried this and it is working for me.
My Test1 class is in default package, just check where your accessing class is in any package, if it is then go back to exact resource folder from classpath like this "../"
public class Test1 {
public static void main(String[] args) {
new Test1();
}
Test1(){
BufferedInputStream file= (BufferedInputStream) this.getClass().getResourceAsStream("resources/a.txt");
try {
System.out.println((char)file.read());
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
FileInputStream file= (FileInputStream)
this.getClass().getResourceAsStream("/resources/Excel.xlsx");
Why do you need FileInputStream? Use
InputStream is = getClass().getResourceAsStream..
Secondly use "resources/Excel.xlsx"
Thirdly when constructing file like this
new
File(System.getProperty("user.dir")+File.separator+"resources"+File.separator+"Excel.xlsx"));
is hard to control slashes. use
new File("parent (userdir property)", "child (resources\Excel.xlsx)")