【问题标题】:Why am I getting 'nullfiles' when trying to copy a file from inside a jar to disk?尝试将 jar 中的文件复制到磁盘时,为什么会出现“nullfiles”?
【发布时间】:2020-01-06 16:52:41
【问题描述】:

我正在尝试将一个文件从我的 JAR 内部复制到 JAR 文件外部的磁盘。我需要复制的文件是大型会计系统的默认配置文件,并且需要在计算机文件系统上。

我搜索了 StackOverflow 以及其他网站(通过 Google 找到)并阅读了大约 50 个答案,我已经尝试了所有这些答案。下面的代码是第一个不是简单地炸毁的代码(使用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,我不明白这是为什么,也不明白这是什么。

【问题讨论】:

  • 您到底想用该代码实现什么?假设资源名为“nwind.conf”并且位于包 com.is2300.isis.resources 中。应该发生什么?为什么要使用 FileInputSTream 来读取不是文件,而是 jar 中的类路径资源?
  • @JBNizet,我正在尝试将位于 com.is2300.isis.resources 中的文件从 JAR 复制到硬盘上某个用户确定位置的文件中。实际上,我认为我在最初问题的第一条语句中对此非常简洁:>我正在尝试将 JAR 内部的文件复制到 JAR 文件外部的磁盘。
  • @JBNizet,谢谢!您实际上提示了正确的关键字进入我的大脑。我想我所需要的只是在头部快速踢一脚,而你提供它真是太棒了。这就是为什么我认为编程应该始终是一项团队运动。
  • “我正在尝试从我的 JAR 中复制一个文件..” Jars 中没有没有文件。它们成为资源,必须通过 URL 处理。

标签: java swing file jar copy


【解决方案1】:

@JBNizet 和@AndrewThompson:

感谢你们两位的cmets。特别是@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";

一切都按我的预期进行。

再次感谢评论的那两位。感谢您的想法和帮助,让我的大脑参与其中。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-11-29
    • 1970-01-01
    • 2017-06-12
    • 2021-09-28
    • 1970-01-01
    • 1970-01-01
    • 2011-04-14
    • 1970-01-01
    相关资源
    最近更新 更多