簡體   English   中英

使用java將文件讀取為1KB塊

[英]Read file as 1KB chunks using java

我試圖從內存中讀取一個文件並將其拆分為1KB塊。

程序的作用是從內存中讀取文件(視頻文件),然后將其拆分為1KB塊。 然后使用SHA-256散列最后一個塊,並將散列附加到第二個最后一個塊。 然后,它計算第二個最后一個塊上的散列和附加的散列,然后將此散列附加到其先前的塊。 這一直持續到第一個塊,它將附加第二個塊的散列。

我只需要第一個塊的哈希值及其附加的哈希值。 我試圖以兩種方式實現這一點,但我認為我做錯了。 有人可以告訴我我做錯了什么。 在沒有解決方案的情況下,我被困在這里6天了。 我已粘貼下面的兩個實現。 任何幫助,將不勝感激。

我已經讀取了整個文件,並嘗試在下面的嘗試中手動將字節數組拆分為1KB塊。

package com.test;

import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.InputStream;
import java.security.MessageDigest;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class ReadFileByteByByte {

    public static void main(String[] args) throws Exception {

        InputStream inStream = null;
        BufferedInputStream bis = null;

        try{
            inStream = new FileInputStream("C:\\a.mp4");

            bis = new BufferedInputStream(inStream);

            int numByte = bis.available();


            byte[] buf = new byte[numByte];
            bis.read(buf, 0, numByte);
            System.out.println(numByte/1024);
            ArrayList<byte[]> a = new ArrayList<>();
            ArrayList<byte[]> b = new ArrayList<>();
            for(int i=0,j=0;i<buf.length;i++,j++){
                byte[] buf2 = new byte[1057];
                buf2[j] = buf[i];
                if(i%1024==1023){
                    a.add(buf2);
                    j=0;
                }
            }

            for(int i=a.size()-1,j=-1;i>=0;i--,j++){
                MessageDigest digest = MessageDigest.getInstance("SHA-256");
                if(i==a.size()-1){
                    byte[] hash = digest.digest(a.get(i));
                    byte[] dest = new byte[a.get(i).length+hash.length];
                    System.arraycopy(a.get(i-1), 0, dest, 0, a.get(i-1).length);
                    System.arraycopy(hash, 0, dest, a.get(i-1).length, hash.length);
                    b.add(dest);
                }
                else{
                    byte[] hash = digest.digest(b.get(0));
                    if(i!=0){
                        byte[] dest = new byte[a.get(i-1).length+hash.length];
                        System.arraycopy(a.get(i-1), 0, dest, 0, a.get(i-1).length);
                        System.arraycopy(hash, 0, dest, a.get(i-1).length, hash.length);
                        b.clear();
                        b.add(dest);
                    }else{
                        System.out.println(bytesToHex(hash));}
                }

            }

        }catch(Exception e){
            e.printStackTrace();
        }finally{
            if(inStream!=null)
                inStream.close();
            if(bis!=null)
                bis.close();
        }   
    }
    final protected static char[] hexArray = "0123456789ABCDEF".toCharArray();
    public static String bytesToHex(byte[] bytes) {
        char[] hexChars = new char[bytes.length * 2];
        for ( int j = 0; j < bytes.length; j++ ) {
            int v = bytes[j] & 0xFF;
            hexChars[j * 2] = hexArray[v >>> 4];
            hexChars[j * 2 + 1] = hexArray[v & 0x0F];
        }
        return new String(hexChars);
    }
}

我在這次嘗試中直接將文件讀取為1KB塊。 在這種嘗試中,由於某種原因,哈希需要很長時間。

package com.test;

import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.InputStream;
import java.security.MessageDigest;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class ReadFileByteByByte2 {

   public static void main(String[] args) throws Exception {

      InputStream inStream = null;
      BufferedInputStream bis = null;

      try{
         inStream = new FileInputStream("C:\\aa.mp4");

         bis = new BufferedInputStream(inStream);

         int numByte = bis.available();

         System.out.println(numByte/1024);
         ArrayList<byte[]> a = new ArrayList<>();
         ArrayList<byte[]> b = new ArrayList<>();
         byte[] buf = new byte[numByte];
         int ii=0;
         while(bis.read(buf, ii, 1024)!=-1){
                 a.add(buf);
         }
         System.out.println(a.size());
         for(int i=a.size()-1,j=-1;i>=0;i--,j++){
             MessageDigest digest = MessageDigest.getInstance("SHA-256");
             if(i==a.size()-1){
                 System.out.println(a.get(i).toString());
                 byte[] hash = digest.digest(a.get(i));
                 byte[] dest = new byte[a.get(i).length+hash.length];
                 System.arraycopy(a.get(i-1), 0, dest, 0, a.get(i-1).length);
                 System.arraycopy(hash, 0, dest, a.get(i-1).length, hash.length);
                 b.add(dest);
             }
             else{
                 System.out.println(i);
                 byte[] hash = digest.digest(b.get(0));
                 if(i!=0){
                     byte[] dest = new byte[a.get(i-1).length+hash.length];
                     System.arraycopy(a.get(i-1), 0, dest, 0, a.get(i-1).length);
                     System.arraycopy(hash, 0, dest, a.get(i-1).length, hash.length);
                     b.clear();
                     b.add(dest);
                 }else{
                 System.out.println(bytesToHex(hash));}
             }

         }

         }catch(Exception e){
            e.printStackTrace();
         }finally{
            if(inStream!=null)
               inStream.close();
            if(bis!=null)
               bis.close();
      } 
   }
   final protected static char[] hexArray = "0123456789ABCDEF".toCharArray();
   public static String bytesToHex(byte[] bytes) {
        char[] hexChars = new char[bytes.length * 2];
        for ( int j = 0; j < bytes.length; j++ ) {
            int v = bytes[j] & 0xFF;
            hexChars[j * 2] = hexArray[v >>> 4];
            hexChars[j * 2 + 1] = hexArray[v & 0x0F];
        }
        return new String(hexChars);
    }
}

任何幫助都非常感謝。 提前致謝。

首先,您必須使用DataInputStream.readFully()來確保您確實獲得1k塊,並確保如果它比其他塊短,則不要在最后一塊上使用它。 read()不保證填充緩沖區,或返回任何大於1的計數。 見Javadoc。

其次,你濫用available(). 它沒有做你正在使用它的東西:它告訴你可以在不阻塞的情況下讀取多少字節 它不能作為EOS測試,也不能獲得流的長度。 見Javadoc。 在這種情況下,您根本不需要它,只需要File.length().

第三,您實際上不需要將塊的哈希附加到塊,因此您可以計算下一個哈希。 只需對塊數據調用digest.update() ,然后將digest.doFinal()提供前一個哈希作為參數,您將獲得完全相同的值。

第四,我想知道你是否正確理解了你的要求。 計算向前方向的哈希值會更有意義。 然后你根本不需要將整個文件讀入內存。 增加的完整性是相同的兩種方式。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM