簡體   English   中英

嘗試將jar中的文件復制到磁盤時,為什么會出現“ nullfiles”?

[英]Why am I getting 'nullfiles' when trying to copy a file from inside a jar to disk?

我正在嘗試將JAR文件外部的文件從JAR內部復制到磁盤。 我將需要復制的文件是大型記帳系統的默認配置文件,並且在計算機文件系統上是必需的。

我搜索了StackOverflow以及其他網站(與Google一起找到的網站),並閱讀了大約五十個答案,我已經嘗試了所有答案。 下面的代碼是第一個沒有被簡單炸毀的代碼(使用NullPointerExceptionFileNotFoundException ),而是實際上試圖獲取位於JAR文件中的資源。

我的JAR文件設置如下:

  • com.is2300.isis
    • MainClass.java(真實名稱太瘋狂了,我現在不想輸入)
  • com.is2300.isis.resources
    • 我要復制到磁盤的資源文件的位置
  • com.is2300.isis.utils
    • 我的類ResourceExporter位置(在底部-底部)具有文件導出方法。

我的MainClass.main()入口點函數:

    public static void main(String[] args) {
        // Test our 'utils.ResourceExporter.exportResource(String resourceName)
        //+ function.

        // Set the start point of our substring to either 5 or 9, depending upon
        //+ if we are debugging (in NetBeans) or not (executing the JAR).
        if ( isDebugging ) {
            startPoint = 5;
        } else {
            startPoint = 9;
        }

        // First, we'll try just the name of the resource file to export.
        String rsName = "nwind.conf";

        try {
            System.out.println(ResourceExporter.exportResource(rsName, 
                    MainClass.class, "/home/user/tmp", startPoint));
        } catch (Exception ex) {
            System.err.println(ex.getCause());
            System.err.println(ex.getMessage());
            ex.printStackTrace(System.err);
        }

        // Then, we'll try it with the absolute path.
        rsName = "/com/is2300/isis/resources/nwind.conf";

        try {
            System.out.println(ResourceExporter.exportResource(rsName, 
                    MainClass.class, "/home/user/tmp", startPoint));
        } catch (Exception ex) {
            System.err.println(ex.getCause());
            System.err.println(ex.getMessage());
            ex.printStackTrace(System.err);
        }

        // Then, we'll try it with the relative path.
        rsName = "../resources/nwind.conf";

        try {
            System.out.println(ResourceExporter.exportResource(rsName, 
                    MainClass.class, "/home/user/tmp", startPoint));
        } catch (Exception ex) {
            System.err.println(ex.getCause());
            System.err.println(ex.getMessage());
            ex.printStackTrace(System.err);
        }

        // Last, we'll try it using dots instead of slashes.
        rsName = "com.is2300.isis.resources.nwind.conf";

        try {
            System.out.println(ResourceExporter.exportResource(rsName, 
                    MainClass.class, "/home/user/tmp", startPoint));
        } catch (Exception ex) {
            System.err.println(ex.getCause());
            System.err.println(ex.getMessage());
            ex.printStackTrace(System.err);
        }

    }

我的ResourceExporter.exportResource()方法:

    public static String exportResource(String resourceName, Class cls, 
                    String outPath, int startPoint) throws Exception {
        File files = new File(cls.getResource(
                cls.getResource(cls.getSimpleName() +
                ".class").toString().substring(
                startPoint, cls.getResource(
                cls.getSimpleName() + ".class").toString().lastIndexOf("/")
                + 1)) + "files");

        InputStream in = new FileInputStream(files);
        FileOutputStream out = new FileOutputStream(outPath + 
                        resourceName.substring(resourceName.lastIndexOf("/")));

        int readBytes;
        byte[] buffer = new byte[4096];
        while ( (readBytes = in.read(buffer)) > 0 )
            out.write(buffer, 0, readBytes);

        in.close();
        out.close();

        return files.getAbsolutePath();
    }

使用我在public static void main(String[] args)所做的事情,我希望對ResourceExporter.exportResource()方法的調用之一實際上導致文件被復制。

但是,當我逐步執行exportResource()方法時,在該行之后的每個調用上:

        File files = new File(cls.getResource(
                cls.getResource(cls.getSimpleName() +
                ".class").toString().substring(
                startPoint, cls.getResource(
                cls.getSimpleName() + ".class").toString().lastIndexOf("/")
                + 1)) + "files");

變量files.getCanonicalPath()調用顯示/home/user/Projects/ProjectName/nullfiles ,我不明白為什么這樣,也不是什么。

@JBNizet和@AndrewThompson:

謝謝你們的評論。 特別是@JBNizet! 您快速地踢了我一下腦袋,使我更加仔細地閱讀了所寫的內容,並立即發現了問題。 非常感謝你。

解決方法是:我沒有做復雜的事情:

        File files = new File(cls.getResource(
                cls.getResource(cls.getSimpleName() +
                ".class").toString().substring(
                startPoint, cls.getResource(
                cls.getSimpleName() + ".class").toString().lastIndexOf("/")
                + 1)) + "files");

        InputStream in = new FileInputStream(files);
        FileOutputStream out = new FileOutputStream(outPath + 
                        resourceName.substring(resourceName.lastIndexOf("/")));

我大約10年前寫的,不記得我在想什么,我能夠簡化為:

        InputStream in = ClassLoader.getSystemClassLoader().getSystemResourceAsStream(resourceName);
        FileOutputStream out = new FileOutputStream(outPath + 
                        resourceName.substring(resourceName.lastIndexOf("/")));

現在,“文件”(表示對@AndrewThompson進行的語義更正)位於JAR文件中。

但是,這不是必須要做的唯一更改。 我在哪里設置傳遞給參數resourceName的變量,也不正確。 我有這樣設置:

String rsName = "/com/is2300/isis/resources/nwind.conf";

但是,不應在前面加上斜杠(/)。 一旦我將上面的行更改為:

String rsName = "com/is2300/isis/resources/nwind.conf";

一切都按照我的預期進行。

再次感謝這兩個評論。 感謝您的想法和協助,以使我的大腦參與其中。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM