ReadFully()冒着窒息的危险?

时间:2013-06-20 00:13:30

标签: java file-io datainputstream bufferedinputstream

我注意到当我在文件而不是read(byte [])上使用readFully()时,处理时间大大减少了。然而,我发现readFully可能是一把双刃剑。如果我偶然尝试读取一个巨大的,几千兆字节的文件,它可能会窒息?

这是我用来生成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一次性接受完整的字节数组,我不知道如何在不填充所有数据的情况下获得校验和,但我想这是另一个问题。另一个线程。

3 个答案:

答案 0 :(得分:4)

你应该只分配一个体积适中的缓冲区(可能是65536个字节),并做一个循环,你一次读取64kb,使用“complete.update()”附加到循环内的消化器。小心最后一个块,这样你只处理读取的字节数(可能小于64kb)

答案 1 :(得分:2)

无论是否使用readFully(),读取文件都需要花费的时间。

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

答案 2 :(得分:1)

如果文件是几千兆字节,那么

readFully()不会阻塞,但是分配该字节缓冲区会。在你调用readFully()之前,你会得到一个内存不足的异常。

您需要使用重复更新散列和文件块的方法,而不是使用整个文件一次更新所有散列。