zoukankan      html  css  js  c++  java
  • 将归档后的文件解档01

    解档

    前情概要

    这篇文章是在上一篇文章如何处理零碎小文件归档的基础上写的。

    串行化(也叫序列化)

    就像过隧道一样,将需要传输的数据排成一排依次传输;
    问: java需要这样的技术,为什么呢?
    答: 因为在网络中传输数据的时候,所有的数据都是以字节的形式来传输(存储)。

    而Java是面相对象编程,那么对象在内存中可能以各种形式存在。那么,当我们需要网络传输或本地存储(实际就是存到磁盘上去)时,我们必须以某种统一的格式(如:xml格式、文本格式、最常见的就是json格式、以对象方式的串行、以二进制方式存储)转化这些数据;这个过程就叫做串行化。

    设计思路

    按照如下顺序依次将文件一个一个的解档出来:

    • 读取4个字节的文件名长度
    • 根据读取到的文件名长度,读取文件名
    • 读取4个字节的文件内容长度
    • 根据读取到的文件内容长度,读取文件内容

    注:
    其中存储的文件名长度和文件内容长度的字节数是可以自己定义的;并且第一次读取文件名的长度时需要判断是否到了文件末尾,如果是则解档结束。

    具体实现方案

    同上一篇文章的Util类:

     1 package com.mmzs.util;
     2 
     3 /**
     4  * @author: mmzs
     5  * @date:   2018年8月9日
     6  * @Description: 
     7  * 博客地址:https://www.cnblogs.com/mmzs/p/9282412.html
     8  * @version V1.0
     9 */
    10 public class Util {
    11     /**
    12      * 将int转化为字节数组
    13      * @return 
    14      */
    15     public static byte[] int2Bytes(int i){
    16         byte[] arr = new byte[4];
    17         arr[0] = (byte) i;
    18         arr[1] = (byte) (i >> 8);
    19         arr[2] = (byte) (i >> 16);
    20         arr[3] = (byte) (i >> 24);
    21         return arr;
    22     }
    23     
    24     /**
    25      * 将字节数组转化为int
    26      */
    27     public static int bytes2Int(byte[] bytes){
    28         int i0 = bytes[0];
    29         int i1 = (bytes[1] & 0xFF) << 8;
    30         int i2 = (bytes[2] & 0xFF) << 16;
    31         int i3 = (bytes[3] & 0xFF) << 24;
    32         return i0 | i1 | i2 | i3;
    33     }
    34 }
    Util

    用来申明一个一个文件的FileBean:

    package com.mmzs.unarchiver;
    
    /**
     * @author: mmzs
     * @date:   2018年8月10日
     * @Description: 
     * 博客地址:https://www.cnblogs.com/mmzs/p/9282412.html
     * @version V1.0
    */
    public class FileBean {
        private String filename;
        private byte[] fileContentBytes;
        
        public FileBean() {
        }
        
        public FileBean(String filename, byte[] fileContentBytes) {
            this.filename = filename;
            this.fileContentBytes = fileContentBytes;
        }
    
        public String getFilename() {
            return filename;
        }
    
        public byte[] getFileContentBytes() {
            return fileContentBytes;
        }
    
        public void setFilename(String filename) {
            this.filename = filename;
        }
    
        public void setFileContentBytes(byte[] fileContentBytes) {
            this.fileContentBytes = fileContentBytes;
        }
    
    }

    实现解档的UnArchiver类:

    package com.mmzs.unarchiver;
    
    import java.io.File;
    import java.io.FileInputStream;
    import java.io.FileNotFoundException;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.util.ArrayList;
    import java.util.List;
    
    import com.mmzs.util.Util;
    
    /**
     * @author: mmzs
     * @date:   2018年8月10日
     * @Description: 归档后的文件解档
     * 博客地址:https://www.cnblogs.com/mmzs/p/9282412.html
     * @version V1.0
    */
    public class UnArchiver {
        
        public static void main(String[] args) throws IOException {
            
            //存放读取出来的一个个文件
            List<FileBean> files = new ArrayList<FileBean>();
            //通过文件输入流,将指定文件转化为流
            FileInputStream fis = new FileInputStream("d:/test/x.xar");
            
            FileBean fileBean = null;
            //将接档后的文件一个一个读取到List数组中
            while ((fileBean = readNextFile(fis)) != null) {
                files.add(fileBean); 
            }
            
            //关闭流
            fis.close();
            
            FileOutputStream fos = null;
            //将文件解压到指定了目录下
            for (FileBean fb : files) {
                fos = new FileOutputStream("d:/test/unarch/"+fb.getFilename());
                fos.write(fb.getFileContentBytes());
                fos.close();
            }
            System.out.println("解档后的文件均已解档到"+"d:/test/unarch/"+"目录下");
        }
        
        /**
         * 从文件输入流中一个文件一个文件的读取
         * @throws IOException 
         */
        public static FileBean readNextFile(FileInputStream fis) throws IOException {
            //因为归档程序Archiver中设置的存储文件名的长度的字节数组长度为4
            byte[] bytes4 = new byte[4]; 
            
            // 1、读取4个字节的bytes4数组中的文件名长度
            int res = fis.read(bytes4);
            if (res == -1) {
                return null;
            }
            //2、
            // 根据读取到的bytes4字节数组中存储的文件名长度
            int fnameLen = Util.bytes2Int(bytes4);
            //读取文件名
            byte[] fnameBytes = new byte[fnameLen];
            fis.read(fnameBytes);
            //得到文件名
            String fname = new String(fnameBytes);
            
            // 3、读取4个字节的bytes4数组中的文件内容长度
            fis.read(bytes4);
            //4、
            // 根据读取到的文件内容长度
            int fcontentLen = Util.bytes2Int(bytes4);
            System.out.println("文件长度"+fcontentLen);
            //读取文件内容
            byte[] fcontentBytes = new byte[fcontentLen];
            fis.read(fcontentBytes);
                 
            return new FileBean(fname, fcontentBytes);
        }
        
    }

    最后附一张工程截图:

    解档效果图:

     不过遇到一个问题,就是 当图片太大的时候,归档后的文件在利用这种方式解档时会出现问题,不出意外,应该是int的范围的关系,大家可以去实操一哈。

  • 相关阅读:
    Power BI for Office 365(八)共享查询
    Power BI for Office 365(七) Power BI站点
    Power BI for Office 365(六)Power Map简介
    Power BI for Office 365(五)Power View第二部分
    Power BI for Office 365(四)Power View第一部分
    Power BI for Office 365(三)Power Pivot
    Power BI for Office 365(二)Power Query
    java 继承、重载、重写与多态
    Android 热修复方案Tinker(一) Application改造
    阿里最新热修复Sophix与QQ超级补丁和Tinker的实现与总结
  • 原文地址:https://www.cnblogs.com/mmzs/p/9469304.html
Copyright © 2011-2022 走看看