0


java实现文件加密解密

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

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

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

1.通过

inputStream.read()

单字节加密,

inputStream.read()

返回的是一个字节的内容(0-255之间的数字),可直接异或加密:

@PostMapping("/swlUpload")publicvoidswlUpload(MultipartFile file)throwsIOException{String originalFilename = file.getOriginalFilename();InputStream inputStream = file.getInputStream();//FileInputStream inputStream = new FileInputStream((File) file);byte[] b =newbyte[1024];FileOutputStream fileOutputStream =newFileOutputStream(newFile("D:\\"+originalFilename));BufferedOutputStream bufferedOutputStream =newBufferedOutputStream(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();}

2.通过

inputStream.read()

单字节解密:

@PostMapping("/swlDownload")publicvoidswlDownload(HttpServletResponse response)throwsIOException{File f2=newFile("D:\\108B计划.xlsx");boolean exists = f2.exists();FileInputStream inputStream =newFileInputStream(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 =newBufferedOutputStream(outputStream);int swl =0;while((swl = inputStream.read())!=-1){
            bufferedOutputStream.write(swl^9527);}//6.2用来刷新缓冲区,刷新后可以再次写出
        bufferedOutputStream.flush();
        inputStream.close();
        bufferedOutputStream.close();}

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

1.通过

inputStream.read(bytes)

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

@PostMapping("/swlUpload")publicvoidswlUpload(MultipartFile file)throwsIOException{String originalFilename = file.getOriginalFilename();InputStream inputStream = file.getInputStream();//FileInputStream inputStream = new FileInputStream((File) file);byte[] b =newbyte[8*1024];FileOutputStream fileOutputStream =newFileOutputStream(newFile("D:\\"+originalFilename));BufferedOutputStream bufferedOutputStream =newBufferedOutputStream(fileOutputStream);//一、整体io读取、循环加密long l =System.currentTimeMillis();
        log.info(String.valueOf(System.currentTimeMillis()));int  swl =0;byte[] bytes =newbyte[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));}

2.通过

inputStream.read(bytes)

加载整个文件解密:

@PostMapping("/swlDownloadAll")publicvoidswlDownloadAll(HttpServletResponse response)throwsIOException{File f2=newFile("D:\\84333c1377d99d970a0984049db926ae.mp4");boolean exists = f2.exists();FileInputStream inputStream =newFileInputStream(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 =newBufferedOutputStream(outputStream);long l =System.currentTimeMillis();
        log.info(String.valueOf(System.currentTimeMillis()));int swl =0;byte[] bytes =newbyte[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.通过

inputStream.read(b)

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

@PostMapping("/swlUploadArray")publicvoidswlUploadArray(MultipartFile file)throwsIOException{String originalFilename = file.getOriginalFilename();InputStream inputStream = file.getInputStream();//FileInputStream inputStream = new FileInputStream((File) file);byte[] b =newbyte[8*1024];FileOutputStream fileOutputStream =newFileOutputStream(newFile("D:\\"+originalFilename));BufferedOutputStream bufferedOutputStream =newBufferedOutputStream(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));}

2.通过

inputStream.read(b)

加载整个文件解密:

@PostMapping("/swlDownloadArray")publicvoidswlDownloadArray(HttpServletResponse response)throwsIOException{File f2=newFile("D:\\84333c1377d99d970a0984049db926ae.mp4");boolean exists = f2.exists();FileInputStream inputStream =newFileInputStream(f2);byte[] b =newbyte[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 =newBufferedOutputStream(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));}

五、解决小数组读取文件流后,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);}}
标签: spring boot

本文转载自: https://blog.csdn.net/qq_38837032/article/details/127751291
版权归原作者 follow_me! 所有, 如有侵权,请联系我们删除。

“java实现文件加密解密”的评论:

还没有评论