我发现自己要在我的软件中解决一个奇怪的错误:问题是只有当我将我的应用程序打包到一个可运行的JAR中时它才会出现。
问题在于这个简单的代码:我添加了loopCounter来计算循环次数
private static byte[] read(InputStream source) {
ByteArrayOutputStream out = new ByteArrayOutputStream();
int loopCounter = 0;
int bytesRead;
try {
byte[] buffer = new byte[4096];
while ((bytesRead = source.read(buffer)) != -1) {
out.write(buffer, 0, bytesRead);
loopCounter++;
}
} catch (IOException e) {
e.printStackTrace();
}
return out.toByteArray();
}
一个例子:
source = ClassLoader.class.getResourceAsStream("file.lol");
loopCounter in Eclipse = 1366
loopCounter in JAR = 1405
我的问题是:为什么同一个InputStream的这个显着差异?
编辑:我用正确的代码更改我的代码,但loopCounters仍然不同。
答案 0 :(得分:7)
InputStream.read()
不保证一次填充整个缓冲区,因此您需要跟踪实际读取的字节数:
byte[] buffer = new byte[4096];
int bytesRead = 0;
while ((bytesRead = source.read(buffer)) != -1) {
out.write(buffer, 0, bytesRead);
loopCounter++;
}
因此,对于InputStream
的不同实现,每次迭代读取的字节数可能会有所不同,因此迭代次数也可能会有所不同。
实际上,InputStream.read()
的特定调用所读取的字节数取决于许多因素。
第一个因素是InputStream
的实现:当您从Eclipse运行应用程序时,使用直接从文件系统读取资源的InputStream
,而当您从jar文件运行它时,使用InputStream
从jar文件中提取资源。显然,jar文件的解压缩算法的一些内部可能会影响你得到的块的大小。
另一个因素是底层环境的行为。例如,从文件系统读取文件的系统调用也可能返回不同大小的块,具体取决于操作系统的某些内部行为,等等。