android中数据的分包

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_21983189/article/details/62886418

之前在开发中,遇到了一个问题,就是在项目assets下有一个apk需要在应用启动时安装到设备中,实现的思路是需要首先将apk拷贝到sdcard中,然后执行安装操作,还有一个问题就是项目中的数据库也需要放在sdcard中,这个apk大约有5M左右,我的数据库大约有30M左右,接下来我就按照普通的I/O流拷贝:

public static boolean copyDataToSD(Context context, String fileName, File strOutFile) {
        InputStream myInput = null;
        OutputStream myOutput = null;
        try {
            myOutput = new FileOutputStream(strOutFile);
            myInput =context.getAssets().open(fileName);
            byte[] buffer = new byte[1024];
            int length = myInput.read(buffer);
            while (length > 0) {
                myOutput.write(buffer, 0, length);
                length = myInput.read(buffer);
            }
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        } finally {
            try {
                if (myOutput != null) {
                    myOutput.flush();
                    myOutput.close();
                }
                if (myInput != null)
                    myInput.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

但是在执行上述代码时,却报错了,经过查询才知道android2.3之后要求从apk拷贝出去的数据必须小于1M,坑爹呀!!!
那么,我们只能将数据分解了!,直接看完整的代码:

public static List<String> splitBigFile(Context context, String fileName, String formatType, String dirName) {
        //需要分割的文件的文件名称
        String base = fileName;
        //需要分割的文件的后缀名
        String ext = formatType;

        List<String> list = new ArrayList<>();

        InputStream inputStream = null;

        //以每个小文件1024*1024字节即1M的标准来分割
        int split = 1024 * 1024;
        byte[] buf = new byte[1024];
        int num = 1;
        try {
            //需要分割的文件的文件
            inputStream = context.getAssets().open(fileName + formatType);
            File fileDir = new File(SDCardUtils.getSDCardPath() + File.separator + dirName);
            if (!fileDir.exists()) {
                fileDir.mkdir();
            }
            while (true) {
                //以"demo"+num+".db"方式来命名小文件即分割后为demo1.db,demo2.db,。。。。。。
                File file = new File(SDCardUtils.getSDCardPath() + File.separator + dirName + File.separator + base + num + ext);
                if (!file.exists()) {
                    file.createNewFile();
                }
                list.add(file.getPath());
                FileOutputStream fos = new FileOutputStream(file);
                for (int i = 0; i < split / buf.length; i++) {
                    int read = inputStream.read(buf);
                    fos.write(buf, 0, read);
                    // 判断大文件读取是否结束
                    if (read < buf.length) {
                        inputStream.close();
                        fos.close();
                        return list;
                    }
                }
                num++;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return list;
    }

    public static boolean mergeFile(Object[] partFileList, String dst, String formatType, String dirName) {
        try {
            OutputStream out = new FileOutputStream(dst);
            byte[] buffer = new byte[1024];
            InputStream in;
            int readLen = 0;
            for (int i = 0; i < partFileList.length; i++) {
                // 获得输入流 ,注意文件的路径
                String str = partFileList[i].toString();
                if (partFileList[i].toString().endsWith(formatType)) {
                    in = new FileInputStream(new File(partFileList[i].toString()));
                    while ((readLen = in.read(buffer)) != -1) {
                        out.write(buffer, 0, readLen);
                    }
                    out.flush();
                    in.close();
                }
            }
            // 把所有小文件都进行写操作后才关闭输出流,这样就会合并为一个文件了
            out.close();

            deleteFolder(SDCardUtils.getSDCardPath() + File.separator + dirName);

            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

public static void deleteFolder(String folderPath) {
      File localFolder = new File(folderPath);
      if (localFolder.isDirectory()) {
            String[] childrenStrings = localFolder.list();
            int length = childrenStrings.length;
            for (int i = 0; i < length; i++) {
                File temp = new File(localFolder, childrenStrings[i]);
                if (temp.isDirectory()) {
                    deleteFolder(temp.getName());
                } else {
                    temp.delete();
                }
            }
            localFolder.delete();
        }
    }

通过上面的代码可以看出实现的思路是:
a.将源文件平均1M大小地分解读取,然后每M流分别写入sdcard中一个小文件中,文件路径存放在一个集合中,这些小文件的命名分别问类似编号:xxx1.db,xxx2.db….等等;
b.在sdcard中创建一个要生成的目标文件,然后通过遍历这些小文件,将每个小文件写入目标文件中;
c.最后关闭流对象,删除这些小文件。

最后,在需要调用的地方:

//第一个参数是上下文,第二个参数是assets下数据包的名字,第三个参数表示数据包的后缀,第四个参数表示要在sdcard中临时存放分解的小文件的文件夹
List<String> strings =CopyDataToSDUtils.splitBigFile(MainActivity.this, "xxx", ".apk", "xxxapk");
boolean b =CopyDataToSDUtils.mergeFile(strings.toArray(), apkPath, ".apk", "hdpapk");
if (b) {
   Log.d(MainActivity.class.getName(),"拷贝成功");
}else{
   Log.d(MainActivity.class.getName(),"拷贝失败");
}

小结:以上是我个人在开发中的一个小插曲,通常我们在例如上传或下载大文件时,为了保证数据包能快速安全并且完整地到达,也会采用分包的处理方式。

猜你喜欢

转载自blog.csdn.net/qq_21983189/article/details/62886418