3

解释我想要达到的目标:

我得到一个文件,我必须从文件中读取数据并创建大小为 1 kb 的块。例如:如果文件大小为 5.8 kb,那么我将有 5 个 1 kb 的块和 1 个 0.8 kb 的最后一个块。在块中包含这些之后,我必须从最后一个块进行 SHA 256 编码并将其附加到倒数第二个块,之后我必须将编码应用于倒数第二个块并将其附加到倒数第三个等等。

问题

如果给我 1024 字节文件大小的倍数,那么我的代码运行良好。但是,如果我的最后一个块大小不是 1024,那么代码就不会按预期工作。

我现在这样做的方式是:

BufferedInputStream bis = new BufferedInputStream(new FileInputStream(f));
int sizeOfBlock = 1024;
int sizeOfHash = 256;

MessageDigest md;
md = MessageDigest.getInstance("SHA-256");

byte[] block = new byte[sizeOfBlock];

List <byte []> blockList = new ArrayList <byte []>();

int tmp = 0;
while ((tmp = bis.read(block)) > 0) {
    System.out.println(tmp);
    blockList.add(block);           
}       

for (int j = blockList.size()-1; j > 0;){
    System.out.println(blockList.get(j).length); // for the first iteration it shouldnt be 1024 if the file size is not a multiple of 1024
    md.update(blockList.get(j--));
    byte[] hash = md.digest();
    byte[] appendBlock = new byte[blockList.get(j).length + hash.length];

    System.arraycopy(blockList.get(j), 0, appendBlock, 0, blockList.get(j).length);
    System.arraycopy(md.digest(), 0, appendBlock, blockList.get(j).length, hash.length);
    blockList.set(j, appendBlock);      
}

System.out.println(blockList.get(0).length);
md.update(blockList.get(0));
byte[] hash = md.digest();

String result = bytesToHex(hash); // converting function from byte to hex
System.out.println(result);
4

2 回答 2

4

您似乎一次又一次地将相同的 1024 字节数组添加到数组列表中。所以当然所有的数组都是 1024 字节。它们是同一个数组。此外,block每次调用 read 时都会覆盖数组,因此它将包含您从文件中读取的最后一个块。您应该将数组的副本存储在数组列表中。

您应该执行以下操作:

while ((tmp = bis.read(block)) > 0) {
    byte[] currentBlock = new byte[tmp];
    System.arraycopy (block, 0, currentBlock, 0, tmp);
    System.out.println(tmp);
    blockList.add(currentBlock);           
} 
于 2013-05-04T15:26:53.173 回答
3

看来错误来自这里:

int tmp = 0;
while ((tmp = bis.read(block)) > 0) {
    System.out.println(tmp);
    blockList.add(block);           
}

数组是java中的引用类型,所以当你传递一个数组时,你就像任何对象一样通过引用传递它。这意味着当您调用时,bis.read(block)您会将字节放入已经分配的数组中。也就是说,您将一个块读入, block,然后将其添加到blocksListthen 当您将另一个块读入同一个变量时,它会替换该数组的内容,因此您实际上添加了 5 个数组副本。

这是您的列表结构

  • 元素 0 ->block
  • 元素 1 ->block
  • 元素 2 ->block

其中所有这些blocks 都是同一个数组。

你真的想要

  • 元素 0 ->block1
  • 元素 1 ->block2
  • 元素 2 ->block3

这些都是不同的数组。您可以通过在每次读取块时分配一个新数组来解决此问题。

现在,这导致了一个问题,因为您希望数组长度短于 1024 字节。但是,因为它是同一个数组,所以数组长度等于 1024 字节,这会触发您的问题。

于 2013-05-04T15:28:41.670 回答