• java实现文件加密解密


    一、对于文件流读写取的方式对比:

    inputStream.read()与OutputStream.write()单字节读取,效率低下
    inputStream.read(new byte[80*1024])与OutputStream.write(new byte[80*1024])固定数组读取,经测试数组增加到80k左右性能最佳
    nputStream.read(inputStream.available()) 与OutputStream.write(inputStream.available())按文件大小一次性读取,如文件过大有内存溢出风险
    BufferedInputStream.read()与BufferedOutputStream.write()默认有一个8K的缓存数组

    二、循环每个字节加解密(此方法效率最低):

    1.通过inputStream.read()单字节加密,inputStream.read()返回的是一个字节的内容(0-255之间的数字),可直接异或加密:

        @PostMapping("/swlUpload")
        public void swlUpload(MultipartFile file) throws IOException {
            String originalFilename = file.getOriginalFilename();
            InputStream inputStream = file.getInputStream();
            //FileInputStream inputStream = new FileInputStream((File) file);
            byte[] b = new byte[1024];
            FileOutputStream fileOutputStream = new FileOutputStream(new File("D:\\"+originalFilename));
            BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(fileOutputStream);
            int  swl = 0;
            while((swl=inputStream.read())!=-1){
                //System.out.println(b);
                bufferedOutputStream.write(swl^9527);
            }
            //6.2用来刷新缓冲区,刷新后可以再次写出
            bufferedOutputStream.flush();
            inputStream.close();
            bufferedOutputStream.close();
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    2.通过inputStream.read()单字节解密:

        @PostMapping("/swlDownload")
        public void swlDownload(HttpServletResponse response) throws IOException {
            File f2= new File("D:\\108B计划.xlsx");
            boolean exists = f2.exists();
            FileInputStream inputStream = new FileInputStream(f2);
            //byte[] b = new byte[1024];
    
            String filePath = "108B计划.xlsx";
            //6.1清除buffer缓存
            response.reset();
            response.setContentType("application/octet-stream;charset=UTF-8");
            //response.setHeader("Content-Disposition", "inline; filename="+ new String(filePath.getBytes("UTF-8"), "ISO-8859-1"));// 定义文件名
            //response.setHeader("Content-Disposition", "attachment; filename="+ new String(filePath.getBytes("UTF-8"), "ISO-8859-1"));// 定义文件名
            response.setHeader("Content-Disposition", "attachment; filename=" + java.net.URLEncoder.encode(filePath, "UTF-8"));
            response.setHeader("Pragma", "no-cache");
            response.setHeader("Cache-Control", "no-cache");
            response.setHeader("Expires", " 0");
            ServletOutputStream outputStream = response.getOutputStream();
            BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(outputStream);
            int swl = 0;
            while((swl = inputStream.read())!=-1){
                bufferedOutputStream.write(swl^9527);
            }
            //6.2用来刷新缓冲区,刷新后可以再次写出
            bufferedOutputStream.flush();
            inputStream.close();
            bufferedOutputStream.close();
        }
    
    
    • 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

    三、加载整个文件加解密(效率快,有内存溢出风险):

    1.通过inputStream.read(bytes) 加载整个文件,inputStream.read(bytes)返回bytes大小的字节,放入bytes数组中,循环异或加密:

        @PostMapping("/swlUpload")
        public void swlUpload(MultipartFile file) throws IOException {
            String originalFilename = file.getOriginalFilename();
            InputStream inputStream = file.getInputStream();
            //FileInputStream inputStream = new FileInputStream((File) file);
            byte[] b = new byte[8*1024];
            
            FileOutputStream fileOutputStream = new FileOutputStream(new File("D:\\"+originalFilename));
            BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(fileOutputStream);
    
            //一、整体io读取、循环加密
            long l = System.currentTimeMillis();
            log.info(String.valueOf(System.currentTimeMillis()));
            int  swl = 0;
            byte[] bytes = new byte[inputStream.available()];
            while((inputStream.read(bytes))!=-1){
                //System.out.println(b);
                for(int i=0;i<bytes.length;i++){
                    bufferedOutputStream.write(bytes[i]^9527);
                }
            }
            //6.2用来刷新缓冲区,刷新后可以再次写出
            bufferedOutputStream.flush();
            inputStream.close();
            bufferedOutputStream.close();
            log.info(String.valueOf(System.currentTimeMillis()));
            log.info(String.valueOf(System.currentTimeMillis()-l));
    
        }
    
    • 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

    2.通过inputStream.read(bytes) 加载整个文件解密:

        @PostMapping("/swlDownloadAll")
        public void swlDownloadAll(HttpServletResponse response) throws IOException {
            File f2= new File("D:\\84333c1377d99d970a0984049db926ae.mp4");
            boolean exists = f2.exists();
            FileInputStream inputStream = new FileInputStream(f2);
            //byte[] b = new byte[1024];
    
            String filePath = "84333c1377d99d970a0984049db926ae.mp4";
            //6.1清除buffer缓存
            response.reset();
            response.setContentType("application/octet-stream;charset=UTF-8");
            //response.setHeader("Content-Disposition", "inline; filename="+ new String(filePath.getBytes("UTF-8"), "ISO-8859-1"));// 定义文件名
            //response.setHeader("Content-Disposition", "attachment; filename="+ new String(filePath.getBytes("UTF-8"), "ISO-8859-1"));// 定义文件名
            response.setHeader("Content-Disposition", "attachment; filename=" + java.net.URLEncoder.encode(filePath, "UTF-8"));
            response.setHeader("Pragma", "no-cache");
            response.setHeader("Cache-Control", "no-cache");
            response.setHeader("Expires", " 0");
            ServletOutputStream outputStream = response.getOutputStream();
            BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(outputStream);
    
            long l = System.currentTimeMillis();
            log.info(String.valueOf(System.currentTimeMillis()));
            int swl = 0;
            byte[] bytes = new byte[inputStream.available()];
            while((inputStream.read(bytes))!=-1){
                for(int i=0;i<bytes.length;i++){
                    bufferedOutputStream.write(bytes[i]^9527);
                }
            }
            //6.2用来刷新缓冲区,刷新后可以再次写出
            bufferedOutputStream.flush();
            inputStream.close();
            bufferedOutputStream.close();
            log.info(String.valueOf(System.currentTimeMillis()));
            log.info(String.valueOf(System.currentTimeMillis()-l));
        }
    
    • 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

    四、小数组加载文件加解密(效率快,无内存溢出风险)【推荐】:

    1.通过inputStream.read(b) 加载整个文件,inputStream.read(b)返回b大小的字节,放入b数组中,循环异或加密:

        @PostMapping("/swlUploadArray")
        public void swlUploadArray(MultipartFile file) throws IOException {
            String originalFilename = file.getOriginalFilename();
            InputStream inputStream = file.getInputStream();
            //FileInputStream inputStream = new FileInputStream((File) file);
            byte[] b = new byte[8*1024];
            FileOutputStream fileOutputStream = new FileOutputStream(new File("D:\\"+originalFilename));
            BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(fileOutputStream);
    
            //三、小数组循环io读取、循环加密
            long l = System.currentTimeMillis();
            log.info(String.valueOf(System.currentTimeMillis()));
            while((inputStream.read(b))!=-1){
                //System.out.println(b);
                for(int i=0;i<b.length;i++){
                    bufferedOutputStream.write(b[i]^9527);
                }
            }
            //6.2用来刷新缓冲区,刷新后可以再次写出
            bufferedOutputStream.flush();
            inputStream.close();
            bufferedOutputStream.close();
            log.info(String.valueOf(System.currentTimeMillis()));
            log.info(String.valueOf(System.currentTimeMillis()-l));
    
        }
    
    • 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

    2.通过inputStream.read(b) 加载整个文件解密:

        @PostMapping("/swlDownloadArray")
        public void swlDownloadArray(HttpServletResponse response) throws IOException {
            File f2= new File("D:\\84333c1377d99d970a0984049db926ae.mp4");
            boolean exists = f2.exists();
            FileInputStream inputStream = new FileInputStream(f2);
            byte[] b = new byte[8*1024];
    
            String filePath = "84333c1377d99d970a0984049db926ae.mp4";
            //6.1清除buffer缓存
            response.reset();
            response.setContentType("application/octet-stream;charset=UTF-8");
            //response.setHeader("Content-Disposition", "inline; filename="+ new String(filePath.getBytes("UTF-8"), "ISO-8859-1"));// 定义文件名
            //response.setHeader("Content-Disposition", "attachment; filename="+ new String(filePath.getBytes("UTF-8"), "ISO-8859-1"));// 定义文件名
            response.setHeader("Content-Disposition", "attachment; filename=" + java.net.URLEncoder.encode(filePath, "UTF-8"));
            response.setHeader("Pragma", "no-cache");
            response.setHeader("Cache-Control", "no-cache");
            response.setHeader("Expires", " 0");
            ServletOutputStream outputStream = response.getOutputStream();
            BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(outputStream);
            long l = System.currentTimeMillis();
            log.info(String.valueOf(System.currentTimeMillis()));
            int swl = 0;
            while((inputStream.read(b))!=-1){
                for(int i=0;i<b.length;i++){
                    bufferedOutputStream.write(b[i]^9527);
                }
            }
            //6.2用来刷新缓冲区,刷新后可以再次写出
            bufferedOutputStream.flush();
            inputStream.close();
            bufferedOutputStream.close();
            log.info(String.valueOf(System.currentTimeMillis()));
            log.info(String.valueOf(System.currentTimeMillis()-l));
        }
    
    • 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

    五、解决小数组读取文件流后,office文档打开异常的问题:

    注意看下面的代码:
    在这里插入图片描述

    原因:这是文档最后一次读取文件,剩余的文件流不足b.length造成的,不足时会在数组中补0,造成上传后的文件与原文件有出入。
    解决方案1:采用byte[] bytes = new byte[inputStream.available()];
    解决方案2(推荐):

            int j;
            while((j=(inputStream.read(b)))!=-1){
                for(int i=0;i<j;i++){
                    bufferedOutputStream.write(b[i]^9527);
                }
            }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
  • 相关阅读:
    【Linux】第四站:Linux基本指令(三)
    十五、MySQL(DCL)如何实现用户权限控制?
    OpenWrt下安装Mosquitto
    23年秋招笔试算法题:美团蔚来
    k8s常用命令
    Kotlin 设置和获取协程名称
    SqlServer 提供的数据迁移方案
    工作以来一直在CRUD,Spring源码该怎么阅读?这份价值百万的源码解析让你如有神助!
    HttpServletResponse实战之下载文件与动态验证码【Javaweb】
    MATLAB绘图
  • 原文地址:https://blog.csdn.net/qq_38837032/article/details/127751291