我是Java的新手,我试图对文件执行MAC计算。 现在由于在运行时不知道文件的大小,我不能只将所有文件加载到内存中。所以我写了代码,所以它会读取位(在这种情况下为4k)。 我遇到的问题是我尝试将整个文件加载到内存中以查看两个方法是否产生相同的哈希值。然而,他们似乎正在产生不同的哈希
这是一点一滴的代码:
FileInputStream fis = new FileInputStream("sbs.dat");
byte[] file = new byte[4096];
m = Mac.getInstance("HmacSHA1");
int i=fis.read(file);
m.init(key);
while (i != -1)
{
m.update(file);
i=fis.read(file);
}
mac = m.doFinal();
这是一次性的方法:
File f = new File("sbs.dat");
long size = f.length();
byte[] file = new byte[(int) size];
fis.read(file);
m = Mac.getInstance("HmacSHA1");
m.init(key);
m.update(file);
mac = m.doFinal();
它们不应该产生相同的哈希吗?
但问题更为通用。第一个代码是将文件加载到内存中并在while循环中执行我们想要执行的任何操作的正确方法吗? (套接字发送,密码文件等...)。 这个问题很有用,因为我看到的每个教程都会一次加载所有内容......
更新:工作:-D。这种方法是否可以通过套接字正确地发送文件?
答案 0 :(得分:5)
没有。您无法保证在fis.read(file)
中会读取file.length
个字节。这就是为什么read()
返回一个int来告诉你它实际读取了多少字节的原因。
你应该这样做:
m.init(key);
int i=fis.read(file);
while (i != -1)
{
m.update(file, 0, i);
i=fis.read(file);
}
利用Mac.update(byte[] data, int offset, int len)方法,允许您在byte []数组中指定实际数据的长度。
答案 1 :(得分:4)
read
函数不一定会填满整个数组。因此,您需要检查从read
函数返回的字节数,并且只使用缓冲区的那么多字节。
答案 2 :(得分:1)
就像Jason LeBrun所说的那样 - read方法并不总是读取指定的字节数。例如:如果文件不包含4096字节的倍数,您认为会发生什么?
我会选择这样的事情:
FileInputStream fis = new FileInputStream(filename);
byte[] buffer = new byte[buffersize];
Mac m = Mac.getInstance("HmacSHA1");
m.init(key);
int n;
while ((n = fis.read(buffer)) != -1)
{
m.update(buffer, 0, n);
}
byte[] mac = m.doFinal();