What is a relative path relative to
I think this may be why you are finding it works but others are finding it doesn’t (It’s not the “real” problem but it is interesting).
A relative path will be relative to the directory you launched the application from (the working directory). And you don’t have to launch it from the gradle project root (or the repository root if those two aren’t the same) . Take this example project
public class DesktopTest{
public static void main(String[] args) {
boolean fileExists = new File("randomFiles/AFile.txt").exists();
System.out.println("Does the file exist? " + fileExists);
}
}
Now if I run this with a normal run configuration with the working directory set as the gradle project root it all works fine
Does the file exist? true
But if I set a different working directory it doesn’t
Does the file exist? false
Possibly you have set your working directory to be somewhere other than the gradle project root and thats why it works for you?
What files make it to your users
All of the above was an aside because by the time these files get to your end users they won’t be files at all, they will either be within the jar (or in my case, in the folder randomFiles
they won’t make it to the end user at all).
If I build a jar file to distribute to the end user
C:\Users\richa\Documents\Development\DesktopTest> gradle jar
Then a get a file DesktopTest.jar. If I now take that to another computer and try to run it I get:
C:\Users\richa\Documents>java -jar DesktopTest.jar
Does the file exist? false
Because the file AFile.txt is still on the development machine. It’s no use to an end user. Things within the resources folder automatically get bundled into the jar (yay!) but once they are in the jar they are not files, they are resources and cannot be referred to as files (this isn’t strictly speaking true, but for our purposes it is). There are special mecanisms for loading “things” from the resources folder. The JMonkeyEngine assetLoader
is one, but would be overkill for this, the class loader is another. If I modify my project to move AFile.txt
to within the resources folder
Then change the way I load the item to use the class loader
public class DesktopTest{
public static void main(String[] args) throws IOException{
ClassLoader classLoader = DesktopTest.class.getClassLoader();
InputStream inputStream = classLoader.getResourceAsStream("AFile.txt");
String aFileContent = new String(inputStream.readAllBytes());
System.out.println("Whats in the file? " + aFileContent);
}
}
Running this, even when compiled into a jar, succeeds and returns:
Whats in the file? Some text
You’ll notice my original example was using this approach to load icons, not using files. File
is for user files really (in our case things like save games) not for things you bundle with your application (unless you go through a really painful distribution process of actually having them as files on the file system, not within the jar)
BufferedImage imageFromResources = ImageIO.read( getClass().getClassLoader().getResourceAsStream("Icons/256.png"))