java - JAR 中 InputStream 的不同行为

标签 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 会出现这种显着差异?

编辑:我用正确的代码更改了我的代码,但循环计数器仍然不同。

最佳答案

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 文件解压缩算法的一些内部结构可能会影响您获得的 block 的大小。

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

关于java - JAR 中 InputStream 的不同行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10914473/

相关文章:

java - 在 AWT (Java) 中排序和显示数组的问题

Java排序与MySQL排序不一样

java - 从服务器检索 pdf 文件流

java - 任何使用大字符串并返回 InputStream 的实用程序类/方法?

java - 在 IntelliJ IDEA 2016.2.3 中显示一个小项目的项目导航器

java - PlayFramework 中缓存中的对象似乎是原始对象?

java - 如何读取 BufferedReader 两次或多次?

java - 在java中读取输入流

java - 在关闭之前是否需要读取/跳过 InputStream 完成?

java - 使用 Jaxb API 将 XML 解码为 Java 对象时获取 NullPointerException