zoukankan      html  css  js  c++  java
  • java语言实现文档的归档解归档

    首先设计归档的协议

    文件归档与解归档
    运用IO流技术,把若干文件以流的方式写到一个文件里去,但是要区分文件和文件之间的边界,就需要设计每个文件的“头”。文件在磁盘上以字节数组的方式存在。“头”包含文件的扩展名类型(1个字节),文件的长度(4个字节),文件内容。解归档:先读文件类型,再读文件长度,接着读文件长度个字节。
    增强版:文件名长度(1个字节长度),文件名字节数组(字符串解码getBytes),文件长度(4个字节),文件内容。

    代码实现归档与解档:

    //Archiver.java

      1 import java.io.FileInputStream;
      2 import java.io.FileOutputStream;
      3 import java.io.IOException;
      4 
      5 public class Archiver {
      6     public void newArchiverFile(String[] srcPaths, String yarPath) {
      7         FileOutputStream fout = null;
      8         try {
      9             //创建yar归档文件的输出流
     10             fout = new FileOutputStream(yarPath);
     11             for(String srcPath : srcPaths) {
     12                 addFile(srcPath, fout);
     13                 
     14             }
     15         } catch (Exception e) {
     16             e.printStackTrace();
     17         } finally {
     18             if (fout != null) {
     19                 try {
     20                     fout.close();
     21                 } catch (IOException e) {
     22                     e.printStackTrace();
     23                 }
     24             }
     25         }
     26     }
     27 
     28     /**
     29      * 向yar归档文件中添加文件
     30      * @param srcPath
     31      * @param fout
     32      */
     33     private void addFile(String srcPath, FileOutputStream fout) {
     34         FileInputStream fin = null;
     35         try {
     36             //1. 取出文件类型
     37             int fType = getFileType(srcPath);
     38             
     39             //2. 取出文件的长度
     40             fin = new FileInputStream(srcPath);
     41             int length = fin.available();
     42             
     43             //3. 将类型写入fout
     44             byte bFType = (byte) fType;
     45             fout.write(new byte[] {bFType});
     46             
     47             //4. 将长度写入yar中
     48             byte[] bytes = Int2ByteArr(length);
     49             fout.write(bytes);
     50             
     51             //5. 写入文件内容
     52             int len = -1;
     53             byte[] buffer = new byte[1024];
     54             while((len = fin.read(buffer)) != -1) {
     55                 fout.write(buffer, 0, len);
     56             }
     57             
     58         } catch (Exception e) {
     59             
     60             e.printStackTrace();
     61         } finally {
     62             if (fin != null) {
     63                 try {
     64                     fin.close();
     65                 } catch (IOException e) {
     66                     e.printStackTrace();
     67                 }
     68             }
     69         }
     70         
     71     }
     72 
     73     private byte[] Int2ByteArr(int i) {
     74         byte[] bytes = new byte[4];
     75         bytes[0] = (byte) i;
     76         bytes[1] = (byte) (i >> 8);
     77         bytes[2] = (byte) (i >> 16);
     78         bytes[3] = (byte) (i >> 24);
     79         return bytes;
     80     }
     81 
     82     /**
     83      * 得到文件类型
     84      * 0-txt
     85      * 1-jpg
     86      * 2-avi
     87      * 3-gif
     88      * 4-exe
     89      * 5-mp4
     90      * @param srcPath
     91      * @return
     92      */
     93     private int getFileType(String srcPath) {
     94         String ext = srcPath.substring(srcPath.lastIndexOf(".")).toLowerCase();
     95         int type = -1;
     96         if (".txt".equals(ext)) {
     97             type = 0;
     98         } else if (".jpg".equals(ext)) {
     99             type = 1;
    100         } else if (".avi".equals(ext)) {
    101             type = 2;
    102         } else if (".gif".equals(ext)) {
    103             type = 3;
    104         } else if (".exe".equals(ext)) {
    105             type = 4;
    106         } else if (".mp4".equals(ext)) {
    107             type = 5;
    108         } else {
    109             type = -1;
    110         }
    111         
    112         return type;
    113     }
    114     
    115     /**
    116      * 向原有yar中添加新文件
    117      */
    118     public void addFile(String srcPath, String yarPath) {
    119         try {
    120             FileOutputStream fos = new FileOutputStream(yarPath,true);//追加
    121             addFile(srcPath, fos);
    122             fos.close();
    123         } catch (Exception e) {
    124             e.printStackTrace();
    125         }
    126     }
    127     
    128     /**
    129      * 解档文件
    130      */
    131     public void unarchive(String yarPath, String destDir) {
    132         try {
    133             FileInputStream fis = new FileInputStream(yarPath);
    134             int i = 1;
    135             //循环读取下一个文件
    136             while (readNextFile(destDir, (i++) + "", fis)) {
    137                 
    138             }
    139             fis.close();    
    140         } catch (Exception e) {
    141             e.printStackTrace();
    142         }
    143         
    144     }
    145 
    146     private boolean readNextFile(String destDir,String name, FileInputStream fis) {
    147         try {
    148             //文件类型
    149             int type = fis.read();
    150             //文件的扩展名
    151             String ext = getFileExt(type);
    152             if (type == -1) {
    153                 return false;
    154             }
    155             
    156             //构造文件
    157             FileOutputStream fout = new FileOutputStream(destDir + "/" + name + ext);
    158             
    159             // 1.读取文件长度
    160             byte[] bytes = new byte[4];
    161             fis.read(bytes);
    162             
    163             // 2.转换字节数组为int
    164             int fileLength = byteArr2Int(bytes);
    165             
    166             // 3.读取文件
    167             byte[] buffer = new byte[1024];
    168 
    169             // 计算读取文件的循环次数
    170             int count = 0;
    171             if (fileLength / buffer.length == 0) {
    172                 count = fileLength / buffer.length;
    173             }
    174             else {
    175                 count = fileLength / buffer.length + 1;
    176             }
    177             //开始循环读取
    178             for (int i = 0; i < count; i++) {
    179                 if (i != (count - 1)) {
    180                     fis.read(buffer);
    181                     fout.write(buffer);
    182                 }
    183                 else {
    184                     byte[] buf0 = new byte[fileLength - ((count - 1) * buffer.length)];
    185                     fis.read(buf0);
    186                     fout.write(buf0);
    187                 }
    188             }
    189             fout.close();
    190             return true;
    191         } catch (Exception e) {
    192             e.printStackTrace();
    193         }
    194         
    195         return false;
    196     }
    197 
    198     private String getFileExt(int type) {
    199         String ext = ".tmp";
    200         switch (type) {
    201         case 0:
    202             ext = ".txt";
    203             break;
    204         case 1:
    205             ext = ".jpg";
    206             break;
    207         case 2:
    208             ext = ".avi";
    209             break;
    210         case 3:
    211             ext = ".gif";
    212             break;
    213         case 4:
    214             ext = ".exe";
    215             break;
    216         case 5:
    217             ext = ".mp4";
    218             break;
    219         default:
    220             ext = ".tmp";
    221             break;
    222         }
    223         return ext;
    224     }
    225 
    226     /**
    227      * 将长度为4的字节数组转换成int
    228      * @param bytes
    229      * @return
    230      */
    231     private int byteArr2Int(byte[] bytes) {
    232         //int i = (int)(bytes[3] << 24 | bytes[2] << 16 | bytes[1] << 8 | bytes[0]);
    233         int i0 = (bytes[3] & 0xff) << 24;
    234         int i1 = (bytes[2] & 0xff) << 16;
    235         int i2 = (bytes[1] & 0xff) << 8;
    236         int i3 = (bytes[0] & 0xff);
    237         return i0 | i1 | i2 | i3;
    238     }
    239 }

    测试代码:

    //App.java

     1 import org.junit.Test;
     2 
     3 public class App {
     4 
     5     /**
     6      * 新建归档文件
     7      */
     8     @Test
     9     public void newArchiveFile() {
    10         Archiver archiver = new Archiver();
    11         String[] srcPaths = { "D:/arch/Sax.JPG", "D:/arch/1.mp4", "D:/arch/java笔记.txt"};
    12         String yarPath = "d:/arch/myYar.yar";
    13         archiver.newArchiverFile(srcPaths, yarPath);
    14         System.out.println("over");
    15     }
    16     
    17     /**
    18      * 向原有归档文件中添加新文件
    19      */
    20     @Test
    21     public void addFile(){
    22         Archiver archiver = new Archiver();
    23         archiver.addFile("D:/arch/hello.txt", "d:/arch/myYar.yar");
    24     }
    25     
    26     /**
    27      * 解档文件
    28      */
    29     @Test
    30     public void unarchiveFile() {
    31         Archiver archiver = new Archiver();
    32         archiver.unarchive("d:/arch/myYar.yar", "d:/arch/unarch");
    33     }
    34 
    35 }

    newArchiveFile()在D:arch目录下生成了myYar.yar归档文件大小为1.MP4 java笔记.txt Sax.jpg三个文件之和加15字节

    unarchiveFile()之后在d:/arch/unarch下还原文件

  • 相关阅读:
    SQL-修改表名,列名
    MySQL必知必会-7、数据过滤
    排序
    Leetcode题解-双指针
    MySQL必知必会-6、过滤数据
    MySQL必知必会-5、排序检索数据
    MySQL必知必会-4、检索数据
    Java容器源码分析-LinkedList
    Java容器源码分析-CopyOnWriteArrayList
    Java容器源码分析-Vector
  • 原文地址:https://www.cnblogs.com/8386blogs/p/7510074.html
Copyright © 2011-2022 走看看