我试图在我的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并将其作为常规文件读取:确定
waveform = AudioFileAPI.readWavFile(new File("C:\\blah\\fromjar.wav"));
使用getResource读取并在AppletAudioClip上调用play()可以获得75%的损坏数据。
Object o = Blah.class.getResource("/blah.wav").getContent();
AppletAudioClip appletAudioClip = (AppletAudioClip) o;
appletAudioClip.play();
通过getResource()读取.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是我自己的类。
答案 0 :(得分:0)
这实际上是由于正在读取资源的InputStream的代码中的错误。如果InputStream的read()
方法由于某种原因没有一次性读取所有字节,则后续{{1}}次尝试将错误地写入始终从位置0开始的同一缓冲区,而不是开始在由目前读取的总字节数确定的位置。
所以,最后,缓冲区看起来像开头有正确数据的碎片,最后是垃圾。
答案 1 :(得分:0)
read()
不保证一次性读取您的文件。如果您阅读InputReader
的文档。它说
从输入流中读取一定数量的字节,并将其存储到缓冲区数组b中。
即使read(byte[] b, int off, int len)
函数签名也不保证它将读取您提供的所有len字节。
从输入流中读取最多len个字节的数据到一个字节数组中。 尝试读取多达len个字节,但可能读取的字节数较小。实际读取的字节数以整数形式返回。
因此,您必须循环执行,直到available()
为零为止。
以下是示例代码,其中还包含有关如何在jar文件中指定文件的信息。
更改jarPath以指向jarFile的位置。然后更改filePath以指向jar内的文件。 如果您的文件位于
someJar.jar \ img \ test.gif
将filePath设置为“ 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();
}