Java JAR中InputStream的不同行为

Java JAR中InputStream的不同行为,java,inputstream,Java,Inputstream,我发现自己解决了软件中的一个奇怪错误:问题是,只有当我将应用程序打包到一个可运行的JAR中时,它才会出现 问题出在这段简单的代码中:我添加了loopCounter来计算循环的次数 private static byte[] read(InputStream source) { ByteArrayOutputStream out = new ByteArrayOutputStream(); int loopCounter = 0; int bytesRead; t

我发现自己解决了软件中的一个奇怪错误:问题是,只有当我将应用程序打包到一个可运行的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.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文件解压算法的某些内部结构可能会影响您得到的块的大小


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

在这两种情况下,该方法是否返回相同的内容?如果使用DataInputStream包装InputStream并尝试使用readFully方法,您可能会得到相同的loopCounter。@SoboLAN我已经修复了代码,现在该方法返回相同的数组,但计数器仍然不同谢谢!我已经和类似的问题斗争了两天了,这就是问题所在。我希望它一次读取整个数组。这个解决方案使该方法在Eclipse和Jar中返回相同的数组,虽然这是正确的,但loopCounter仍然是正确的different@integeruser字体没关系。特定调用
read()
读取的字节数取决于许多因素,因此
循环计数器的值不必相等。我知道了,但我的问题是:这些因素是什么?:)对不起,英语不是我的母语