JAR中的InputStream具有不同的行为

时间:2012-06-06 12:44:15

标签: java inputstream

我发现自己要在我的软件中解决一个奇怪的错误:问题是只有当我将我的应用程序打包到一个可运行的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仍然不同。

1 个答案:

答案 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文件的解压缩算法的一些内部可能会影响你得到的块的大小。

另一个因素是底层环境的行为。例如,从文件系统读取文件的系统调用也可能返回不同大小的块,具体取决于操作系统的某些内部行为,等等。