当前位置: 首页 > 知识库问答 >
问题:

访问JAR中的Java资源会返回大约75%的垃圾

解鸿运
2023-03-14

我正在尝试在JAR文件中加载WAV资源文件。当通过IDE运行时,它可以完美地工作。但是当通过java-jar运行时,它会给我大约75%的垃圾和25%的正确数据。我想知道为什么。以下是我尝试过的几种方法:

>

  • (我的首选方法):使用来自JAR的getResourceAsStream读取会给出包含原始部分的损坏数据:

    short[] waveform = AudioFileAPI.readWavFile(
        Blah.class.getResourceAsStream("/blah.wav"));
    

    从常规文件读取:确定

    waveform = AudioFileAPI.readWavFile(new File("C:\\blah\\blah.wav"));
    

    从创建的JAR中提取wav并将其作为常规文件读取:OK

    waveform = AudioFileAPI.readWavFile(new File("C:\\blah\\fromjar.wav"));
    

    在AppletAudioClip上使用getResource读取并调用play()可以提供75%的损坏数据,如上所述。

    Object o = Blah.class.getResource("/blah.wav").getContent();
    AppletAudioClip appletAudioClip = (AppletAudioClip) o;
    appletAudioClip.play();
    

    通过getResources(). openStream()读取:如上所述,75%的数据损坏。

    InputStream is = Blah.class.getResource("/blah.wav").openStream();
    waveform = AudioFileAPI.readWavFile(is);
    

    解压和重新压缩JAR并重新运行程序也没有帮助。

    总结一下,上述所有方法在从IDE运行时都能完美运行,但指定的方法在作为资源加载时会失败。JAR由IntelliJ IDEA打包。我使用JDK 1.8版。0_131。AudioFileAPI是我自己的类。

  • 共有2个答案

    何辰沛
    2023-03-14

    read()不能保证一次性读取文件。如果您阅读了InputReader的文档。上面写着

    从输入流中读取一定数量的字节,并将其存储到缓冲区数组b中。

    即使是read(byte[]b, int off, int len)函数签名也不能保证它会读取您提供的所有len字节。

    从输入流中读取多达len字节的数据到字节数组中。尝试读取尽可能多的len字节,但可能会读取更小的数字。实际读取的字节数以整数形式返回。

    因此必须循环,直到available()为零。

    下面是一个示例代码,它还介绍了如何在jar文件中指定文件

    更改jarPath以指向jarFile的位置。然后将filePath更改为指向jar内的文件。如果您的文件在

    someJar。jar\img\test。gif格式

    将文件路径设置为“img\test.gif”

    File executable = new File(jarPath);
    JarFile jar = new JarFile(executable);
    InputStream fileInputStreamReader = jar.getInputStream(jar.getJarEntry(filePath));
    byte[] bytes = new byte[fileInputStreamReader.available()];
    
    int sizeOrig = fileInputStreamReader.available();
    int size = fileInputStreamReader.available();
    int offset = 0;
    while (size != 0){
        fileInputStreamReader.read(bytes, offset, size);
        offset = sizeOrig - fileInputStreamReader.available();
        size = fileInputStreamReader.available();
    }
    
    魏风华
    2023-03-14

    这实际上是由于读取资源输入流的代码中有一个bug造成的。如果InputStream的read()方法由于任何原因没有一次性读取所有字节,那么后续的read()尝试将错误地写入相同的缓冲区,总是从位置0开始,而不是从迄今为止读取的字节总数确定的位置开始。

    因此,最终,缓冲区看起来在开始时包含正确数据的片段,在结束时包含垃圾。

     类似资料:
    • 问题内容: 我有一个包含要分发的资源(主要是缓存,日志记录等的配置)的文件。 我对这些资源的相对路径有疑问,所以我做了在另一个stackoverflow问题中发现的问题,该问题说这是有效的方法: 不幸的是,这不起作用。 有任何想法吗?谢谢! PS:显然我不能使用绝对路径,如果可能,我想避免使用环境变量 问题答案: 确保资源文件夹在项目设置中列为源文件夹。另外,确保在构建jar时将资源文件夹设置为导

    • 问题内容: 我有一个带有工具栏的Java项目,该工具栏上带有图标。这些图标存储在名为resources /的文件夹中,因此路径可能是“ resources / icon1.png”。该文件夹位于我的src目录中,因此在编译后,该文件夹将被复制到bin / 我正在使用以下代码访问资源。 (imageName将为“ resources / icon1.png”等)。在Eclipse中运行时,效果很好。

    • 问题内容: 嗨,我已经将我的Java项目导出为可执行jar文件。在我的项目中,我正在访问包含一些数据的Excel文件。现在,当我尝试访问Excel文件时,我将无法访问它。 我的项目结构是: Java_Project_Folder -src_Folder -resources_Folder(包含Excel文件) 我正在像访问Excel文件 我尝试使用以下方式访问此文件: 但是我进入的是空异常。有什么

    • 我希望连接到Microsoft Graph API,并与OneDrive上的一个小型Excel工作簿进行交互。 我能够通过Graph API成功授权并连接到OneDrive,查询我个人的OneDrive内容,甚至可以找到.xlsx工作簿并获取其ID。对此终结点的请求成功: 这是Microsoft Graph/O365业务帐户

    • 问题内容: 在我的应用程序中,我以这种方式加载资源: 这给了我: 当我从IDE运行我的应用程序时,但是当我运行应用程序的jar时,这可以很好地工作: 路径变为: 有什么办法解决这个问题? 我将使用“存储库”目录名称来创建此目录: 以相同的方式,我将获得一个文件名(而不是目录),并以这种方式使用它: 问题答案: 听起来你正在尝试使用或类似方法加载资源。不要那样做:不要调用,而是从中调用并读取数据。

    • 我正在尝试访问res/stringsxml中的字符串值: 编辑:在onCreate()中初始化 不管用