为什么getResourceAsStream()和带FileInputStream的读取文件返回不同长度的数组?

时间:2014-10-02 06:13:23

标签: java io

我想将文件作为字节数组读取,并意识到读取字节的数量因使用的方法而异。这里有相关代码:

    public byte[] readResource() {
    try (InputStream is = getClass().getClassLoader().getResourceAsStream(FILE_NAME)) {
        int available = is.available();
        byte[] result = new byte[available];
        is.read(result, 0, available);

        return result;
    } catch (Exception e) {
        log.error("Failed to load resource '{}'", FILE_NAME, e);
    }

    return new byte[0];
}

public byte[] readFile() {
    File file = new File(FILE_PATH + FILE_NAME);
    try (InputStream is = new FileInputStream(file)) {
        int available = is.available();
        byte[] result = new byte[available];
        is.read(result, 0, available);

        return result;
    } catch (Exception e) {
        log.error("Failed to load file '{}'", FILE_NAME, e);
    }

    return new byte[0];
}

调用File.length()并使用FileInputStream进行读取会为给定的测试文件返回21566字节的正确长度,但将文件作为资源读取将返回21622字节。

有谁知道为什么我得到不同的结果以及如何修复它以便readResource()返回正确的结果?

2 个答案:

答案 0 :(得分:4)

  

为什么getResourceAsStream()和带FileInputStream的读取文件返回不同长度的数组?

因为您在Javadoc中以特别警告的方式滥用available()方法:

  

“使用此方法的返回值来分配用于保存此流中所有数据的缓冲区是绝对正确的。”

  

有谁知道为什么我得到不同的结果以及如何修复它以便readResource()返回正确的结果?

读入循环直到流结束。

答案 1 :(得分:3)

根据InputStream的API docsInputStream.available()不返回资源的大小 - 它返回

  

估计可以从此输入流中无阻塞地读取(或跳过)的字节数

要从流中获取资源的大小,您需要完全读取流,并计算读取的字节数。

要读取流并将内容作为字节数组返回,您可以执行以下操作:

    try (   InputStream is = getClass().getClassLoader().getResourceAsStream(FILE_NAME);
            ByteArrayOutputStream bos = new ByteArrayOutputStream()) {

        byte[] buffer = new byte[4096];
        int bytesRead = 0;
        while ((bytesRead = is.read(buffer)) != -1) {
            bos.write(buffer, 0, bytesRead);
        }
        return bos.toByteArray();

    }