如何将超大Base64字符串解码为文件?

写这篇技术文章的初衷,是因为工作需要将巨大base64字符串解码为二进制文件,在百度和google了一番后,发现网上根本没有现成的解决方案,大部分文章都是复制粘贴的。

说实话,首次看到这个问题,大部分人都会疑惑,到底是什么样的应用场景会用base64编码来处理大文件,这岂不自寻烦恼吗?其实很多场景都会遇到大文件的Base64解码问题,例如安卓中的webview处理blob文件下载的时候,如果遇到较大的文件(100M以上),需要将超大Base64文本解析为二进制文件。

先来分析下这个问题的原因,一般搞开发的都知道base64编码很大程度上是简化了我们传输文件的方式,特别是对于没有文件系统的团队来说,更是难得,但是这里的文件仅仅指的是小文件、小图片(如:头像、二维码等)之类的,因为大文件转化出来的base64编码真的很长很长,先说这不利于网络传输,就算勉强传输过去了,数据库也不见得能存储下来,就算勉强存储下来了,重新再获取的时候也一定会影响速度和效率。

base64编码出来的长度实际上是没有大小限制的,因为base64要求把每三个8Bit的字节转换为四个6Bit的字节(3*8 = 4*6 = 24),然后把6Bit再添两位高位0,组成四个8Bit的字节,也就是说,转换后的字符串理论上将要比原来的长1/3。

解决方法

按照上述对base64的分析,只需要将超大字符串按照4的倍数进行截取后,再进行解码,然后通过FileOutputStream输出流,依次将字节数组写入文件即可。下面是实现的代码,解码效率也是比较高的。另外,如果您需要参考其他的应用是如何实现某些功能的逻辑代码,可以通过百度搜索 安卓修改大师 来将apk文件直接转换为可编译可打包的android studio源代码,本解决方案就是参考了 装酷神器 的源代码来实现的。

        public static void DecodeHugeBase64ToFile(String fileContent, String outputFile) {
            File myCaptureFile = null;
            FileOutputStream fos= null;
            try {
                myCaptureFile = new File(outputFile);
                if (!myCaptureFile.exists()) {
                    myCaptureFile.createNewFile();
                }
                String filepath = myCaptureFile.getAbsolutePath();

                File file = new File(filepath);
                if (file.exists()) {
                    file.delete();
                }
                 fos = new FileOutputStream(file);

                int len = 500 * 1024;// * 1024; 这里调整每次解码的文本大小
                int txtLen = fileContent.length();
                int pages = (int) Math.ceil((double) txtLen / (double) len);
                for (int i = 0; i < pages; i++) {
                    int lastPos = (i + 1) * len;
                    if (lastPos > txtLen) lastPos = txtLen;
                    String temp = fileContent.substring(i * len, lastPos);
                    byte[] respBytes = Base64.decode(temp, Base64.DEFAULT);
                    fos.write(respBytes);
                }
                fos.flush();
            } catch (IOException e) {
                e.printStackTrace();
            }
            finally {
               if(fos!=null) {
                   try {
                       fos.close();
                   } catch (IOException e) {
                       e.printStackTrace();
                   }
               }
            }
        }
  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值