0

I'm working on a very small java project, in which I load the application settings from a JSON file, in the IDE (IntelliJ) it works all fine, finds the file and works properly, but when I build the jar and execute it from the command line, it throws FileNotFoundException. what could be the cause of that?

Here is some of my code:

1- With this class, I get the path of the JSON file:

package sample.Utils;

public class JsonFilePLace {
private final String JSONPATH;

public JsonFilePLace(){
    JSONPATH =  getClass().getResource("/sample/data/loadData.json").getPath();
    String path = getClass().getResource("/sample/data/loadData.json").getPath();
    System.out.println(path);
}

public String getJSONPATH() {
    return JSONPATH;
}
}

This is the new method which reads the JSON File:

public class JsonParsers {
static String fileContent;


public JsonParsers() throws URISyntaxException, IOException {
    final URL resource = this.getClass().getResource("/loadData.json");
    final Path path = Paths.get(resource.toURI());
    final byte[] bytes = Files.readAllBytes(path);
    fileContent = new String(bytes);

}

public static SettingsObject getSettings(/*String filePath*/) {


    JSONParser jparser = new JSONParser();


    SettingsObject returnedObject = null;


    try {
        Object object = jparser.parse(/*new FileReader(filePath)*/fileContent);
        JSONObject jObject = (JSONObject) object;

        String name = (String) jObject.get("user");
        String matricule = (String) jObject.get("matricule");

        JSONArray jArray = (JSONArray) jObject.get("tarifaction");
        FormulaClass A = null, B = null, C = null;
        int counter = 0;

        for (Object obj : jArray) {
            JSONObject jObj = (JSONObject) obj;
            if (counter == 0)
                A = new FormulaClass((double) jObj.get("distance"), (double) jObj.get("heure"));
            if (counter == 1)
                B = new FormulaClass((double) jObj.get("distance"), (double) jObj.get("heure"));
            if (counter == 2)
                C = new FormulaClass((double) jObj.get("distance"), (double) jObj.get("heure"));

            counter++;
        }

        JSONObject staticsObject = (JSONObject) jObject.get("statics");

        String reservation_1 = String.valueOf(staticsObject.get("reservation_1"));
        String reservation_2 = String.valueOf(staticsObject.get("reservation_2"));
        String prise_charge = (String.valueOf(staticsObject.get("prise_charge")));
        String tva = String.valueOf(staticsObject.get("tva"));

        String savePath = (String) jObject.get("save_path");

        returnedObject = new SettingsObject(name, matricule, A, B, C, reservation_1, reservation_2, prise_charge, tva, savePath);

    } catch (ParseException e) {
        e.printStackTrace();
    }


    return returnedObject;
}

This is the main method:

public class Main extends Application {

// TODO: 19/03/2019 maybe instanciate the settings variable here

public static final String JSONPATH = "loadData.json";

public static SettingsObject GLOBAL_SETTINGS;


@Override
public void start(Stage primaryStage) throws IOException {
    Parent root = FXMLLoader.load(getClass().getResource("uis/sample.fxml"));
    primaryStage.setTitle("Taxi Manager");
    primaryStage.setScene(new Scene(root, 820, 766));
    primaryStage.centerOnScreen();
    primaryStage.show();
}


public static void main(String[] args) throws IOException, URISyntaxException {
    JsonParsers jparsers = new JsonParsers();
    GLOBAL_SETTINGS = jparsers.getSettings();
    launch(args);
}

}

this is the cmd error, knowing it runs just fine from the editor:

C:\Users\Simou\Desktop\Work\WorK\TaxiProgram\out\artifacts\TaxiProgramFr>java -j
ar TaxiProgramFr.jar
java.lang.reflect.InvocationTargetException
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
        at java.lang.reflect.Method.invoke(Unknown Source)
        at 
com.sun.javafx.application.LauncherImpl.launchApplicationWithArgs(Lau
ncherImpl.java:389)
        at 
com.sun.javafx.application.LauncherImpl.launchApplication(LauncherImp
l.java:328)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
        at java.lang.reflect.Method.invoke(Unknown Source)
        at sun.launcher.LauncherHelper$FXHelper.main(Unknown Source)
Caused by: java.nio.file.FileSystemNotFoundException
        at 
com.sun.nio.zipfs.ZipFileSystemProvider.getFileSystem(ZipFileSystemPr
ovider.java:171)
        at 
com.sun.nio.zipfs.ZipFileSystemProvider.getPath(ZipFileSystemProvider
.java:157)
        at java.nio.file.Paths.get(Unknown Source)
        at sample.Utils.JsonParsers.<init>(JsonParsers.java:24)
        at sample.Main.main(Main.java:36)
        ... 11 more
    Exception running application sample.Main

this is the writer method:

public static void settingsWriter(SettingsObject settings, String filePath) {
    JSONObject gObj = new JSONObject();
    JSONArray jsonArray = new JSONArray();
    JSONObject staticsOBJ = new JSONObject();

    gObj.put("user", settings.getUserName());
    gObj.put("matricule", settings.getMatricule());

    JSONObject tempObj = new JSONObject();
    tempObj.put("distance", settings.getA().getDistance());
    tempObj.put("heure", settings.getA().getHeure() * 60);
    jsonArray.add(tempObj);

    tempObj = new JSONObject();
    tempObj.put("distance", settings.getB().getDistance());
    tempObj.put("heure", settings.getB().getHeure() * 60);
    jsonArray.add(tempObj);

    tempObj = new JSONObject();
    tempObj.put("distance", settings.getC().getDistance());
    tempObj.put("heure", settings.getC().getHeure() * 60);
    jsonArray.add(tempObj);

    gObj.put("tarifaction", jsonArray);

    staticsOBJ.put("reservation_1", Integer.parseInt(settings.getReservation_1()));
    staticsOBJ.put("reservation_2", Integer.parseInt(settings.getReservation_2()));
    staticsOBJ.put("prise_charge", Double.parseDouble(settings.getPrise_Charge()));
    staticsOBJ.put("tva", Integer.parseInt(settings.getTva()));

    gObj.put("statics", staticsOBJ);

    gObj.put("save_path", settings.getPathSave());

    File jsonFile = new File(filePath);

    try {
            FileWriter fileWriter = new FileWriter(jsonFile);
            fileWriter.write(gObj.toJSONString());
            fileWriter.flush();
            fileWriter.close();
    } catch (IOException e) {
        e.printStackTrace();
    }

}
  • 1
    https://stackoverflow.com/questions/20389255/reading-a-resource-file-from-within-jar – Dylan Mar 20 '19 at 13:41
  • You did not post the code causing the issue: `sample.Utils.JsonParsers.username`... – fabian Mar 20 '19 at 14:11
  • @fabian the usernam method is a little part from the getSettings, which i posted, it is exactly the same, and my problem is the file not found, because all the methods are using the same path variable. –  Mar 20 '19 at 14:16
  • Never call `getPath()` on a URL. It does not return a valid file name. Read the URL’s InputStream directly instead. (Also, instead of providing a picture of the exception’s stack trace, edit your question and add the full stack trace as text. Don’t worry about its length; preformatted text blocks are scrollable here. Images are hard to read, impossible to search, and cannot be understood by sight impaired users.) – VGR Mar 20 '19 at 14:20

1 Answers1

1

You're storing your textual file inside a source package. Thus, the file will most likely be stripped away during compilation, unless you explicitly configured to not do so.

If you still want to store them there, what you need to do is

final URL resource = YourClass.class.getResource("/sample/data/loadData.json");
final Path path = Paths.get(resource.toURI());
final byte[] bytes = Files.readAllBytes(path);
final String fileContent = new String(bytes);

YourClass.class.getResource("/sample/data/loadData.json");

Here /sample/data/loadData.json is the absolute package path.


What I recommend instead is storing those files under a resource folder.

YourClass.class.getResource("loadData.json");

What you need to do is delete JsonFilePLace, it's not needed at all!
Do this instead

final URL resource = YourClass.class.getResource("loadData.json");
final Path path = Paths.get(resource.toURI());
final byte[] bytes = Files.readAllBytes(path);
final String fileContent = new String(bytes);

final Object object = jparser.parse(fileContent);
final JSONObject jObject = (JSONObject) object;

Being that this doesn't seem to work, directly access the File resource

try (final InputStream is = YourClass.class.getResourceAsStream("loadData.json")) {
    final String fileContent = readString(is);
    final Object object = jparser.parse(fileContent);
    final JSONObject jObject = (JSONObject) object;
    ...
}

private static String readString(final InputStream inputStream) throws IOException {
    final ByteArrayOutputStream result = new ByteArrayOutputStream();
    final byte[] buffer = new byte[1024];
    int length;

    while ((length = inputStream.read(buffer)) != -1) {
        result.write(buffer, 0, length);
    }

    return result.toString(StandardCharsets.UTF_8);
}
LppEdd
  • 20,274
  • 11
  • 84
  • 139
  • Comments are not for extended discussion or debugging sessions; this conversation has been [moved to chat](https://chat.stackoverflow.com/rooms/190401/discussion-on-answer-by-lppedd-file-not-found-when-running-jar). Please be sure to [edit] the answer to include any relevant findings. – Cody Gray - on strike Mar 20 '19 at 23:07
  • any new ideas please? –  Mar 21 '19 at 14:34
  • @wassimchaguetmi hi! I'm at work now, I'll be at home in a couple hours. – LppEdd Mar 21 '19 at 14:34
  • i don't want to take much of your time, you know my code, i need just a little hint, or a link to a guide, if you don't mind of course. –  Mar 22 '19 at 11:42
  • @wassimchaguetmi you're right, I'm sorry. This is a good approach to read a file from the File System https://www.mkyong.com/java/how-to-read-file-in-java-fileinputstream/ If the file must be in the same directory, you just need a relative path, instead of an absolute one – LppEdd Mar 22 '19 at 11:44