访问 JAR returns 中的 Java 资源大约 75% 是垃圾
Accessing Java resource inside JAR returns about 75% garbage
我正在尝试在我的 JAR 文件中加载 WAV 资源文件。当通过 IDE 连接 运行 时,它工作得很好。但是当 运行ning 通过 java -jar
时,它给了我大约 75% 的垃圾和 25% 的正确数据。我想知道为什么。以下是我尝试过的几种方法:
(我的首选方法):使用 JAR 中的 getResourceAsStream 读取会得到损坏的数据,其中包含原始数据的某些部分:
short[] waveform = AudioFileAPI.readWavFile(
Blah.class.getResourceAsStream("/blah.wav"));
从常规文件读取:OK
waveform = AudioFileAPI.readWavFile(new File("C:\blah\blah.wav"));
从创建的 JAR 中提取 wav 并将其作为常规文件读取:OK
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 是我自己的 class.
这实际上是由于读取资源的 InputStream 的代码中存在错误。如果 InputStream 的 read()
方法由于某种原因没有一次读取所有字节,后续 read()
尝试将错误地写入同一缓冲区,始终从位置 0 开始,而不是从确定的位置开始到目前为止读取的总字节数。
所以,最后,缓冲区看起来像是在开头有正确数据的片段,在结尾却有垃圾。
read()
不保证一次性读取您的文件。如果您阅读 InputReader
的文档。它说
Reads some number of bytes from the input stream and stores them into the buffer array b.
即使是 read(byte[] b, int off, int len)
函数签名也不能保证它会读取您提供的所有 len 个字节。
Reads up to len bytes of data from the input stream into an array of bytes. An attempt is made to read as many as len bytes, but a smaller number may be read. The number of bytes actually read is returned as an integer.
所以你必须循环直到 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();
}
我正在尝试在我的 JAR 文件中加载 WAV 资源文件。当通过 IDE 连接 运行 时,它工作得很好。但是当 运行ning 通过 java -jar
时,它给了我大约 75% 的垃圾和 25% 的正确数据。我想知道为什么。以下是我尝试过的几种方法:
(我的首选方法):使用 JAR 中的 getResourceAsStream 读取会得到损坏的数据,其中包含原始数据的某些部分:
short[] waveform = AudioFileAPI.readWavFile( Blah.class.getResourceAsStream("/blah.wav"));
从常规文件读取:OK
waveform = AudioFileAPI.readWavFile(new File("C:\blah\blah.wav"));
从创建的 JAR 中提取 wav 并将其作为常规文件读取:OK
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 是我自己的 class.
这实际上是由于读取资源的 InputStream 的代码中存在错误。如果 InputStream 的 read()
方法由于某种原因没有一次读取所有字节,后续 read()
尝试将错误地写入同一缓冲区,始终从位置 0 开始,而不是从确定的位置开始到目前为止读取的总字节数。
所以,最后,缓冲区看起来像是在开头有正确数据的片段,在结尾却有垃圾。
read()
不保证一次性读取您的文件。如果您阅读 InputReader
的文档。它说
Reads some number of bytes from the input stream and stores them into the buffer array b.
即使是 read(byte[] b, int off, int len)
函数签名也不能保证它会读取您提供的所有 len 个字节。
Reads up to len bytes of data from the input stream into an array of bytes. An attempt is made to read as many as len bytes, but a smaller number may be read. The number of bytes actually read is returned as an integer.
所以你必须循环直到 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();
}