CopyStreamUtils.java 2.77 KB
Newer Older
liqin's avatar
liqin committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74
package cn.wisenergy.chnmuseum.party.common.util;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.io.SequenceInputStream;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import java.util.Vector;

public class CopyStreamUtils {

    /**
     * @param inputStream
     * @return
     */
    public static Map<String, Object> copyInputStream(InputStream inputStream) {

        /*
         * 	因为inputStream只能读取一次,
         * 	所以将其进行复制
         * 	复制方法是通过定义一个byteArrayOutputStream
         * 	然后将byteArrayOutputStream转化为InputStream
         * 	但是这样存在一个问题,就是当文件比较大的时候,会出现内存溢出
         * 	将jvm参数调整也效果不佳
         * 	所以解决方案为采用分段的方法,将原本的inputStream分成很多小的inputStream
         * 	然后通过SequenceInputStream进行合并输入流
         * 	合并后的SequenceInputStream和原来的输入流相同,达到复制的效果
         *
         */
        ByteArrayOutputStream baos;

        // 每次读取1024字节
        byte[] buffer = new byte[1024];
        int readNum;

        // 定义一个Vector,用来存储分段后的小的InputStream,最后用于构造SequenceInputStream和并流
        Vector<InputStream> streams = new Vector<>();

        // 为提高效率,在此处进行流处理的时候,直接进行md5校验码的生成,节省资源
        String MD5String = "";
        InputStream sequenceInputStream = null;

        try {
            while ((readNum = inputStream.read(buffer)) > -1) {
                baos = new ByteArrayOutputStream();
                baos.write(buffer, 0, readNum);

                // 更新md5校验码的输入流
                Md5Utils.updateFileMD5String(buffer, readNum);

                // 分段的复制inputStream,每次将新产生的小段流与原来的合并
                streams.add(new ByteArrayInputStream(baos.toByteArray()));

                // 不同于其他输出流,二进制流无法通过flush进行刷新,所以只能通过close之后再重新new来充值二进制流
                baos.close();
            }

            // 生成md5校验码
            MD5String = Md5Utils.getFileMD5String();
            // 通过之前的分段的小的inputStream进行构造合并流
            Enumeration<InputStream> e = streams.elements();
            sequenceInputStream = new SequenceInputStream(e);
        } catch (Exception e) {
            e.printStackTrace();
        }
        Map<String, Object> map = new HashMap<>();
        map.put("md5", MD5String);
        map.put("inputStream", sequenceInputStream);
        return map;
    }

}