3

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

4

1 回答 1

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 文件运行它时,您使用它从 jar 文件InputStream中提取资源。显然,jar 文件的一些解压算法内部可能会影响您获得的块的大小。

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

于 2012-06-06T13:02:35.000 回答