Java 预先计算文件流校验和

Java 预先计算文件流校验和,java,java-io,java.nio.file,Java,Java Io,Java.nio.file,我正在努力确保输出文件的完整性,以防磁盘空间不足、网络问题或流式传输到文件过程中可能发生的任何异常。 是否有方法在写入磁盘之前预先计算FileStream校验和,然后检查文件是否正确写入。 对我来说,这听起来有点荒谬,一个系统通过校验和来验证自己导出的XML的完整性,通常情况下,另一端的工作是验证使用的文件是否与另一个系统生成的文件相符 但这是我必须执行的一项要求 她是我作为文件编写的流: String xmlTransfer =""; File testFile = new Fil

我正在努力确保输出文件的完整性,以防磁盘空间不足、网络问题或流式传输到文件过程中可能发生的任何异常。 是否有方法在写入磁盘之前预先计算FileStream校验和,然后检查文件是否正确写入。 对我来说,这听起来有点荒谬,一个系统通过校验和来验证自己导出的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();

不,您无法预先计算有多少数据将来自流。这根本不是流的工作方式


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

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

第二种方法是在写入文件系统之前先有一个内存流,但它会消耗内存

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


关于这个问题,MD5检查对我来说太慢了。

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

您可以在读取流时计算MD5

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

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

  • 在保存时动态计算MD5,保存后再次检查MD5(如果您在linux上,可以使用md5sum)
  • 第一次计算MD5,第二次保存文件
  • 比如说

    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");
    
    
        }
    }
    
    然后

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

    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");
        }
    
    }
    
    导入java.io.BufferedReader;
    导入java.io.BufferedWriter;
    导入java.io.ByteArrayInputStream;
    导入java.io.File;
    导入java.io.FileInputStream;
    导入java.io.FileNotFoundException;
    导入java.io.FileOutputStream;
    导入java.io.FileWriter;
    导入java.io.IOException;
    导入java.io.InputStream;
    导入java.io.InputStreamReader;
    导入java.io.OutputStream;
    导入java.security.MessageDigest;
    公共类CheckSumFileTest
    {
    私有文件buildChecksumFile(文件fileToCheck、字符串filePrefix、字符串checksumAlgorithm)引发异常
    {
    字符串校验和=null;
    文件checksumFile=null;
    字符串tempDir=System.getProperty(“java.io.tmpdir”);
    试一试{
    checksumFile=新文件(tempDir,filePrefix+“+”+checksumfalgorithm.toLowerCase());
    checksumFile.createNewFile();
    checksumFile.deleteOnExit();
    }捕获(异常e1){
    e1.printStackTrace();
    抛出e1;
    }
    FileWriter fw=null;
    试一试{
    校验和=校验和(fileToCheck,checksum算法);
    fw=新文件写入程序(checksumFile);
    fw.写入(校验和);
    }捕获(例外e){
    e、 printStackTrace();
    投掷e;
    }
    最后
    {
    如果(fw!=null)
    fw.close();
    }
    返回检查文件;
    }
    私有静态字符串校验和(文件文件、字符串校验和算法)引发异常
    {
    MessageDigest=MessageDigest.getInstance(checksumAlgorithm);
    InputStream输入=null;
    StringBuffer sb=新的StringBuffer();
    试一试{
    输入=新文件输入流(文件);
    字节[]缓冲区=新字节[8192];
    做{
    int read=输入.读取(缓冲区);
    
    if(读取如何在读取文件流时计算MD5,保存后再次检查?如果在计算MD5时出现问题,我将无法知道写入磁盘的结果文件是否有效。如果我在计算MD5时遇到任何问题,我将假定我必须再次写入该文件。。。(别忘了添加max retries)thx对于提示答案,异常解决方案的问题是,由于文件被另一个进程使用,我无法删除该文件,这是一个奇怪的问题,即使我确保每个流都已正确关闭。
    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");
        }
    
    }