preCalculate文件流校验和

时间:2014-02-05 10:22:05

标签: java java-io java.nio.file

我正在尝试确保在磁盘空间不足,网络问题或在流式传输到文件进程期间可能发生的任何anyException的情况下输出文件完整性。 有没有办法在写入磁盘之前预先计算FileStream checkSum,然后检查文件是否写得正确。 对我来说这听起来有点荒谬,系统通过checkSum验证自己导出的XML的完整性,通常,另一端的工作是验证消耗的文件是否符合其他系统生成的文件。

但这是我必须实施的要求。

她是我作为文件写的流:

 String xmlTransfer ="";
    File testFile =  new File("testFile.xml");
    InputStream in = new ByteArrayInputStream(xmlTransfer.getBytes("utf-8"));
    FileOutputStream out = new FileOutputStream(testFile)
     byte[] buffer = new byte[2048];
               int bytesRead;
               while ((bytesRead = in.read(buffer)) != -1) {
                   out.write(buffer, 0, bytesRead);
               }
               out.close();
               in.close();

4 个答案:

答案 0 :(得分:3)

不,您无法预先知道流中会有多少数据。这根本不是流的工作方式。

如果您正在编写代码的两端,您可以做的是先在发送端计算文件大小,然后在发送文件内容之前发送。

答案 1 :(得分:3)

最好的方法是捕捉异常。如果出现问题,将启动异常,在这种情况下您可以删除部分写入的文件。

第二种方法是在写入文件系统之前拥有内存中的流,但它会消耗内存。

第三种方法是确保目标磁盘容量(新文件(路径).getFreeSpace())

对于这个问题,MD5检查听起来太慢了。

答案 2 :(得分:1)

您应该通过MD5检查,而不是文件大小

您可以在阅读流时计算MD5。

请参阅https://stackoverflow.com/a/304350/3230038

然后,在保存文件后,您可以再次生成md5并进行比较

更新 - 这是我对此的更详细的想法。我假设您只想计算MD5而不必将整个byte []带入内存。在这种情况下,我认为你有2个选项

  1. 在保存时动态计算MD5,保存后再次检查md5(如果你在linux上,你可以使用md5sum)
  2. 在第一遍中计算MD5,然后在第二遍中保存文件。
  3. 例如

    import java.io.File;
    import java.io.FileInputStream;
    import java.io.IOException;
    import java.io.InputStream;
    import java.security.DigestInputStream;
    import java.security.MessageDigest;
    import java.security.NoSuchAlgorithmException;
    
    import org.apache.commons.io.IOUtils;
    import org.apache.commons.io.output.NullOutputStream;
    
    
    public class MD5OnTheFly {
    
        /**
         * @param args
         * @throws NoSuchAlgorithmException 
         * @throws IOException 
         */
        public static void main(String[] args) throws NoSuchAlgorithmException, IOException {
    
            long ini = System.currentTimeMillis();
    
            File file = new File("/home/leoks/Downloads/VirtualBox-4.3.0.tar");
    
            System.out.println("size:"+file.length());
    
            InputStream is = new FileInputStream(file);
    
            MessageDigest md = MessageDigest.getInstance("MD5");
    
            DigestInputStream dis = new DigestInputStream(is, md);
    
            IOUtils.copy(dis, new NullOutputStream());
    
            byte[] digest = md.digest();
    
            StringBuffer hexString = new StringBuffer();
            for (int i = 0; i < digest.length; i++) {
                String hex = Integer.toHexString(0xff & digest[i]);
                if (hex.length() == 1)
                    hexString.append('0');
                hexString.append(hex);
            }
    
            System.out.println(hexString);
    
            long end = System.currentTimeMillis();
            System.out.println(end-ini+" millis");
    
    
        }
    }
    

    返回

    410859520
    dda81aea75a83b1489662c6bcd0677e4
    1413 millis
    

    然后

    [leoks@home ~]$ md5sum /home/leoks/Downloads/VirtualBox-4.3.0.tar
    dda81aea75a83b1489662c6bcd0677e4  /home/leoks/Downloads/VirtualBox-4.3.0.tar
    [leoks@home ~]$ 
    

答案 3 :(得分:1)

试试这个:

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.security.MessageDigest;


public class CheckSumFileTest 
{

    private File buildChecksumFile(File fileToCheck, String filePrefix, String checksumAlgorithm) throws Exception
    {
        String checksum = null;
        File checksumFile = null;
        String tempDir = System.getProperty("java.io.tmpdir");
        try {
            checksumFile = new File(tempDir, filePrefix+"."+ checksumAlgorithm.toLowerCase());
            checksumFile.createNewFile();
            checksumFile.deleteOnExit();
        } catch (Exception e1) {
            e1.printStackTrace();
            throw e1;
        }
        FileWriter fw = null;
        try {
            checksum = checkSum(fileToCheck,checksumAlgorithm);
            fw = new FileWriter(checksumFile);
            fw.write(checksum);
        } catch (Exception e) {
            e.printStackTrace();
            throw e;
        }
        finally
        {
            if(fw !=null)
                fw.close();
        }

        return checksumFile;
    }

    private static String checkSum(File file, String checksumAlgorithm) throws Exception
    {
        MessageDigest digest = MessageDigest.getInstance(checksumAlgorithm);

        InputStream input = null;
        StringBuffer sb = new StringBuffer();
        try{
            input = new FileInputStream(file);
            byte[] buffer = new byte[8192];
            do {
                int read = input.read(buffer);
                if(read <= 0)
                    break;
                digest.update(buffer, 0, read);
            } while(true);
            byte[] sum = digest.digest();

            for (int i = 0; i < sum.length; i++) {
                sb.append(Integer.toString((sum[i] & 0xff) + 0x100, 16).substring(1));
            }

        }catch(IOException io)
        {

        }finally{
            if(input != null)
                input.close();
        }

        return sb.toString();
    }

    private static String checkSumInStream(InputStream stream, String checksumAlgorithm) throws Exception
    {
        MessageDigest digest = MessageDigest.getInstance(checksumAlgorithm);

        InputStream input = null;
        StringBuffer sb = new StringBuffer();
        try{
            input = stream;
            byte[] buffer = new byte[8192];
            do {
                int read = input.read(buffer);
                if(read <= 0)
                    break;
                digest.update(buffer, 0, read);
            } while(true);
            byte[] sum = digest.digest();

            for (int i = 0; i < sum.length; i++) {
                sb.append(Integer.toString((sum[i] & 0xff) + 0x100, 16).substring(1));
            }

        }catch(IOException io)
        {

        }finally{
            if(input != null)
                input.close();
        }

        return sb.toString();
    }

    private boolean checkIntegrity(String targetFileName, String checksumFileName, String checksumAlgorithm) throws Exception
    {
        FileInputStream stream = null;
        BufferedReader br = null;
        InputStreamReader ipsr = null;
        File checksumFile = null;
        String checksumString="";
        File targetFile = new File(targetFileName);
        try{
            checksumFile = new File(checksumFileName);
            stream = new FileInputStream(checksumFile);
            ipsr = new InputStreamReader(stream);
            br = new BufferedReader(ipsr);

            //In checksum file : only one line to read
            checksumString = br.readLine();

        }finally
        {
            if(br != null)
                br.close();
            if(ipsr != null)
                ipsr.close();
            if(stream != null)
                stream.close();
        }


        if(checksumString.equals(checkSum(targetFile,checksumAlgorithm)))
        {
            return true;
        }
        else
        {
            return false;
        }
    }



    /**
     * @param args
     */
    public static void main(String[] args) 
    {
        String str = "Amine";
        InputStream stream = new ByteArrayInputStream(str.getBytes());
        //step1
        try {
            System.out.println(checkSumInStream(stream,"MD5"));
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        //step2
        File file = new File("c:/test.txt");

        // if file doesnt exists, then create it
        if (!file.exists()) {
            try {
                file.createNewFile();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }

        FileWriter fw;
        BufferedWriter bw;

        try {
            fw = new FileWriter(file.getAbsoluteFile());
            bw = new BufferedWriter(fw);
            bw.write(str);
            bw.close();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        try {
            System.out.println(checkSum(file, "MD5"));
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        System.out.println("Done");
    }

}