FaithReaper FaithReaper - 3 months ago 11
Java Question

JAR reading file from relative location, "file:\" part added when execute `jar` but not as project

With these two methods below, I want to read a file within

src/com/WindThunderStudio/resources
to read/load user input in my application:

private void saveInputToFile() {
String[][] input = new String[7][4];

//save data to array

String uri = Constants.INPUT_DATA_PATH;
URL url = getClass().getResource(uri);
File f = null;
System.out.println("Writing data...");
if (url != null) {
System.out.println("Input data path: " + url.getFile());
f = new File(url.getFile());
} else {
System.out.println("URL is null. Searching for parent folder. ");
String uriNoQuery = uri.substring(0, uri.lastIndexOf("/"));
System.out.println("uriNoQuery is: " + uriNoQuery);
url = getClass().getResource(uriNoQuery);
if (url != null) {
f = new File(url.getFile() + File.separator + uri.substring(uri.lastIndexOf("/") + 1, uri.length()));
System.out.println("Supposed file absolute path: " + f.getAbsolutePath());
System.out.println("Supposed file path: " + f.getPath());
} else {
System.out.println("Cannot construct the URL with " + uriNoQuery);
}
}
try {
if (!f.exists()) {
if (f.createNewFile()){
System.out.println("Succeeded in creating file. ");
} else {
System.out.println("Creating file failed. ");
}

}
ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(f));
out.writeObject(input);
out.close();
} catch (Exception e) {
e.printStackTrace();
}
}

private void recoverInputFromFile() {
try {
System.out.println("Reading data...");
String uri = Constants.INPUT_DATA_PATH;
URL url = getClass().getResource(uri);
if (url != null){ //if the URL is found. If not found, is null.
System.out.println("Input data path: " + url.getFile());
File f = new File(url.getFile());
if (f.exists()){
System.out.println("File exists. Path: " + f.getAbsolutePath());
ObjectInputStream in = new ObjectInputStream(new FileInputStream(f));
String[][] input = new String[7][4];
input = (String[][])in.readObject();

//recover data from `input`

in.close();
} else {
System.out.println("File doesn't exist. " + url.getFile());
}
} else {
System.out.println("URI is null. " + uri);
}
} catch (Exception e) {
e.printStackTrace();
}
}


, where

Constants.INPUT_DATA_PATH = "/com/WindThunderStudio/resources/inputData.txt";


When the application runs, it searches if there's a
URL
existante with given path. If not, doesn't do anything. When quiting, it examines if with the given path, an object of
URL
can be constructed, if not, changes to the parent folder, and creates a file in this folder, and writes data into it.

When run as a java project in Eclipse, it is all fine. First time:

Reading data...
URI is null. /com/WindThunderStudio/resources/inputData.txt
Writing data...
URL is null. Searching for parent folder.
uriNoQuery is: /com/WindThunderStudio/resources
Supposed file absolute path: Y:\CtrlRecau_WinSuite_DYL\desarrollo\workspace_NEW\CalSaldoFichaje\bin\com\WindThunderStudio\resources\inputData.txt
Supposed file path: Y:\CtrlRecau_WinSuite_DYL\desarrollo\workspace_NEW\CalSaldoFichaje\bin\com\WindThunderStudio\resources\inputData.txt
Succeeded in creating file.


And data are saved. Second time running, data are restored into the table, and I got these lines in console:

Reading data...
Input data path: /Y:/CtrlRecau_WinSuite_DYL/desarrollo/workspace_NEW/CalSaldoFichaje/bin/com/WindThunderStudio/resources/inputData.txt
File exists. Path: Y:\CtrlRecau_WinSuite_DYL\desarrollo\workspace_NEW\CalSaldoFichaje\bin\com\WindThunderStudio\resources\inputData.txt
Writing data...
Input data path: /Y:/CtrlRecau_WinSuite_DYL/desarrollo/workspace_NEW/CalSaldoFichaje/bin/com/WindThunderStudio/resources/inputData.txt


But, if I package it as a runnable jar(I chose to
Extract library from jar
when packaging), I got these errors:

First time running:

d:\desarrollo>java -jar Cal6.jar
Reading data...
URI is null. /com/WindThunderStudio/resources/inputData.txt
Writing data...
URL is null. Searching for parent folder.
uriNoQuery is: /com/WindThunderStudio/resources
Supposed file absolute path: d:\desarrollo\file:\D:\desarrollo\Cal6.jar!\com\WindThunderStudio\resources\inputData.txt
Supposed file path: file:\D:\desarrollo\Cal6.jar!\com\WindThunderStudio\resources\inputData.txt
java.io.IOException: El nombre de archivo, el nombre de directorio o la sintaxis de la etiqueta del volumen no son correctos
at java.io.WinNTFileSystem.createFileExclusively(Native Method)
at java.io.File.createNewFile(File.java:1006)
at com.WindThunderStudio.UI.MainFrame$4.saveInputToFile(MainFrame.java:777)
at com.WindThunderStudio.UI.MainFrame$4.windowClosed(MainFrame.java:711)
at java.awt.Window.processWindowEvent(Window.java:2054)
at javax.swing.JFrame.processWindowEvent(JFrame.java:296)
at java.awt.Window.processEvent(Window.java:2009)
at java.awt.Component.dispatchEventImpl(Component.java:4872)
at java.awt.Container.dispatchEventImpl(Container.java:2287)
at java.awt.Window.dispatchEventImpl(Window.java:2719)
at java.awt.Component.dispatchEvent(Component.java:4698)
at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:747)
at java.awt.EventQueue.access$300(EventQueue.java:103)
at java.awt.EventQueue$3.run(EventQueue.java:706)
at java.awt.EventQueue$3.run(EventQueue.java:704)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:76)
at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:87)
at java.awt.EventQueue$4.run(EventQueue.java:720)
at java.awt.EventQueue$4.run(EventQueue.java:718)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:76)
at java.awt.EventQueue.dispatchEvent(EventQueue.java:717)
at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:242)
at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:161)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:150)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:146)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:138)
at java.awt.EventDispatchThread.run(EventDispatchThread.java:91)


The cause of exception in Spanish means the file name, the folder name, or the path's syntax is wrong.

Second time running is the same, because the previous run didn't write data. So nothing is stored neither recovered.

I noticed the
file:\
part when I execute the
jar
file, and I believe it's the problem. I have tried to get rid of the leading
/
in the constant path, but it's not ok.

If someone can help me, it would be so nice of you.

The project is available in GitHub here:

https://github.com/WesleyBlancoYuan/SWING.git

or,

git@github.com:WesleyBlancoYuan/SWING.git

Answer

Finally these lines helped me:

//1. read the path of the .class file/JAR. Working in both cases.
String  path = URLDecoder.decode(getClass().getProtectionDomain().getCodeSource().getLocation().getPath(), "UTF-8");

//2. get the parent folder path where the .class file/JAR is located.
//Note: "path" only contains "/", not File.separator, because it's an URL.
String appPath = path.substring(0, lastIndexOf("/"));

//3. Construct a File with the parent folder + separator + file name.
File f = new File(appPath + File.seperator + "someFileName.txt");

Then, check if it exists and so on.

Comments