2011-04-15 20 views
5

我在Java中是一个新手,我试图对文件执行MAC计算。 现在由于文件的大小在运行时不知道,所以我不能将所有文件加载到内存中。所以我编写了代码,以便能够读取位(本例中为4k)。 我遇到的问题是我试图将整个文件加载到内存中,以查看两种方法是否产生相同的散列。但是他们似乎产生不同的散列Java将文件读入内存以及如何不炸掉内存

这里是由位码位:

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。此方法是否可以正确地通过套接字发送文件?

回答

4

read函数不一定会填满整个数组。所以,你需要检查从read函数返回了多少字节,并且只使用缓冲区的很多字节。

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)方法,可以让你在字节指定实际数据的长度[]数组。

+0

卫生署。我觉得自己像一个白痴,我完全忘记了在Mac课程中有3种更新方法。然而,我仍然会在一些简单的事情上浪费时间。要尝试一下,但听起来不错。 – ptguy 2011-04-15 20:07:16

1

就像Jason LeBrun所说 - 读取方法不会总是读取指定的字节数。例如:如果文件不包含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(); 
相关问题