有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java为什么我在尝试将文件从jar内部复制到磁盘时会得到“nullfiles”?

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

我搜索过StackOverflow,以及其他网站(通过谷歌找到),读过大约50个答案,我都试过了。下面的代码不是第一个简单地爆炸(使用NullPointerExceptionFileNotFoundException)的代码,而是实际尝试获取位于JAR文件中的资源

我的JAR文件设置如下:

  • com。是2300。伊斯兰国
    • 主课。java(实际名称非常长,我现在不想把它打印出来)
  • com。是2300。伊斯兰国。资源
    • 要复制到磁盘的资源文件的位置
  • com。是2300。伊斯兰国。乌提尔斯
    • 具有文件导出方法的类ResourceExporter(位于底部)的位置

MyMainClass.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,我不理解这是为什么,也不理解这是什么


共 (1) 个答案

  1. # 1 楼答案

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

    一切都按照我预期的方式进行

    再次感谢两位发表评论的人。我感谢你的想法和帮助,让我的大脑活跃起来