运行 Jar 时找不到文件

File not found when running Jar

我正在做一个非常小的 java 项目,我在其中从 JSON 文件加载应用程序设置,在 IDE (IntelliJ) 中一切正常,找到文件并正常工作,但是当我构建 jar 并从命令行执行它时,它会抛出 FileNotFoundException。 可能是什么原因造成的?

这是我的一些代码:

1- 通过这个 class,我得到了 JSON 文件的路径:

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;
}
}

这是读取 JSON 文件的新方法:

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;
}

这是主要方法:

public class 主要扩展应用程序 {

// 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);
}

}

这是 cmd 错误,从编辑器中知道它运行正常:

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

这是写法:

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();
    }

}

您正在将文本文件存储在源代码包中。因此,该文件很可能会在编译过程中被删除,除非您明确配置为不这样做。

如果您还想将它们存储在那里,您需要做的是

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");

这里/sample/data/loadData.json是包的绝对路径


我建议将这些文件存储在 resource 文件夹下。

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

你需要做的就是删除JsonFilePLace,根本不需要!
改为这样做

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;

因为这似乎不起作用,直接访问 File 资源

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);
}