3

私が達成しようとしていることの説明:

ファイルが与えられ、ファイルからデータを読み取り、サイズが 1 kb のブロックを作成する必要があります。例: ファイル サイズが 5.8 kb の場合、それぞれ 1 kb の 5 つのブロックと 0.8 kb の最後の 1 つのブロックがあります。これらをブロックに含めた後、最後のブロックから SHA 256 エンコーディングを実行し、最後から 2 番目のブロックに追加する必要があります。その後、エンコーディングを最後から 2 番目のブロックに適用し、最後から 3 番目のブロックに追加する必要があります。

問題

ファイル サイズが 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 バイトになります。それらは同じ配列です。さらに、blockread を呼び出すたびに配列を上書きしているため、ファイルから読み取った最後のブロックが含まれます。配列のコピーを配列リストに保存する必要があります。

次のようなことをする必要があります:

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それを に追加してからblocksList、別のブロックを同じ変数に読み込むと、その配列の内容が置き換えられるため、実際には配列の 5 つのコピーを追加したことになります。

これがあなたのリスト構造です

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

これらblockの s はすべて同じ配列です。

あなたは本当に欲しい

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

これらはすべて異なる配列です。これは、ブロックを読み取るたびに新しい配列を割り当てることで修正できます。

配列の長さが 1024 バイトよりも短いことが予想されるため、これが問題を引き起こしています。ただし、同じ配列であるため、配列の長さが 1024 バイトになり、問題が発生します。

于 2013-05-04T15:28:41.670 に答える