3

我注意到当我readFully()在文件上使用而不是 read(byte[]) 时,处理时间大大减少。但是,我突然想到 readFully 可能是一把双刃剑。如果我不小心尝试读取一个巨大的、数 GB 的文件,它会窒息吗?

这是我用来生成 SHA-256 校验和的函数:

public static byte[] createChecksum(File log, String type) throws Exception {
    DataInputStream fis = new DataInputStream(new FileInputStream(log));
    Long len = log.length();
    byte[] buffer = new byte[len.intValue()];
    fis.readFully(buffer); // TODO: readFully may come at the risk of
                            // choking on a huge file.
    fis.close();
    MessageDigest complete = MessageDigest.getInstance(type);
    complete.update(buffer);
    return complete.digest();
}

如果我改为使用:

DataInputStream fis = new DataInputStream(new BufferedInputStream(new FileInputStream(log)));

这会减轻这种风险吗?或者...是始终控制读取的字节量并使用循环直到读取所有字节的最佳选择(在您无法保证数据大小的情况下)?

(想想看,由于 MessageDigest API 一次接收完整的字节数组,我不确定如何在不一次填充所有数据的情况下获得校验和,但我想这是另一个线程的另一个问题。

4

3 回答 3

4

您应该只分配一个大小合适的缓冲区(可能是 65536 字节),然后执行一个循环,一次读取 64kb,使用“complete.update()”附加到循环内的消化器。在最后一个块上要小心,所以你只处理读取的字节数(可能小于 64kb)

于 2013-06-20T00:17:29.030 回答
2

无论您是否使用 readFully() ,读取文件都将花费尽可能长的时间。

您是否可以实际分配千兆字节大小的字节数组是另一个问题。下载文件时根本不需要使用 readFully() 。它用于有线协议,其中接下来的 12 个字节是标识符,后跟另外 60 个字节的地址信息,您不希望继续编写循环。

于 2013-06-20T01:04:07.927 回答
1

如果文件是多个千兆字节,readFully() 不会阻塞,但分配该字节缓冲区会。在调用 readFully() 之前,您会遇到内存不足异常。

您需要使用重复使用文件块更新哈希的方法,而不是使用整个文件一次全部更新。

于 2013-06-20T00:47:13.067 回答