JAR 从相对位置读取文件,"file:\" 部分在执行 `jar` 时添加但不是作为项目

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

使用下面这两种方法,我想在我的应用程序中读取 src/com/WindThunderStudio/resources 到 read/load 用户输入的文件:

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

,其中

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

当应用程序 运行s 时,它会搜索是否存在具有给定路径的 URL existante。如果没有,则不执行任何操作。退出时,检查给定的路径是否可以构建URL的对象,如果不能,则切换到父文件夹,并在该文件夹中创建一个文件,并向其中写入数据。

当运行作为Eclipse中的java项目时,一切正常。第一次:

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. 

并保存数据。第二次 运行ning,数据恢复到 table,我在控制台中得到这些行:

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

但是,如果我将其打包为 运行nable jar(我在打包时选择 Extract library from jar),我会收到以下错误:

第一次运行宁:

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.saveInputToFile(MainFrame.java:777)
        at com.WindThunderStudio.UI.MainFrame.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.access0(EventQueue.java:103)
        at java.awt.EventQueue.run(EventQueue.java:706)
        at java.awt.EventQueue.run(EventQueue.java:704)
        at java.security.AccessController.doPrivileged(Native Method)
        at java.security.ProtectionDomain.doIntersectionPrivilege(ProtectionDomain.java:76)
        at java.security.ProtectionDomain.doIntersectionPrivilege(ProtectionDomain.java:87)
        at java.awt.EventQueue.run(EventQueue.java:720)
        at java.awt.EventQueue.run(EventQueue.java:718)
        at java.security.AccessController.doPrivileged(Native Method)
        at java.security.ProtectionDomain.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)

西班牙语中的异常原因是指文件名、文件夹名或路径语法错误。

第二次运行ning也是一样,因为上次运行没有写入数据。所以什么都没有存储也没有恢复。

我在执行 jar 文件时注意到 file:\ 部分,我认为这是问题所在。我试图去掉常量路径中的前导 /,但不行。

如果有人能帮助我,那你就太好了。

该项目在 GitHub 中可用:

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

或者,

git@github.com:WesleyBlancoYuan/SWING.git

最后这些行帮助了我:

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

然后,检查是否存在等等。