• 将归档后的文件解档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的范围的关系,大家可以去实操一哈。

  • 相关阅读:
    win7游戏窗口设置
    怎么在 html 中 动态的加载一个 script
    nodejs+express +jade模板引擎 新建项目
    将大数据利用 BCP 导出SqlServer数据到CSV
    产品经理如何赢得开发人员的尊重和支持?-摘自infoq
    Microsoft TFS 如何显示在Windows 的上下文菜单中
    使用PowerDesigner 设计SQL Server 数据库
    sqlserver 删掉日志文件ldf以后 救命语句
    SqlServer修改数据库文件及日志文件存放位置
    快速备份sqlserver2005以上版本数据库的方法-摘自网络
  • 原文地址:https://www.cnblogs.com/mmzs/p/9469304.html
Copyright © 2020-2023  润新知