如何处理零碎小文件归档:
tar
har
jar
war
ear
0、关键点:
设计协议(因为协议不一样的话,可能各种软件解档出来的内容会发生变化)
1、前情概要
位运算:
0000 0100 = 4
0000 1010 = 10
1111 1111 = -1
0000 0001 = 1
0000 0101 = 5
- & 与
- | 或
- ~ 按位取反
~5 = 1111 1010 = -6 - ^ 按位异或(相同为0,不同为1)
-1^1 = 1 0000 0000 = 0
2、设计思路
1、设计int和字节数组互相转换的工具类
实现关键:位运算
2、分别按如下顺序将多个零碎小文件归档:
(1)存入文件名长度利用Util工具类转化为字节数组,并存到总字节数组;
(2)存入文件名内容利用f.getName().getBytes转化为字节数组,并存到总字节数组;
(3)存入文件内容长度利用Util工具类转化为字节数组,并存到总字节数组;
(4)将文件内容转化为字节数组[利用文件输入字节流FileInputStream读取,利用字节数组输出流ByteArrayOutputStream进行保存],并利用.toByteArray()方法将保存的字节数组输出流转化为字节数组,然后保存到总字节数组。
3、设计要点
//文件 File f = new File(path); //读取文件内容到数组中 FileInputStream fis = new FileInputStream(f); //缓存数组 byte[] buf = new byte[1024]; //记录缓存数组长度 int len0 = 0 ; //判断文件是否读取完毕 //本来读到的是-128至127;但是在此处read已经将读取到的字节转化成了0~255 while(((len0 = fis.read(buf)) != -1)){ baos.write(buf, 0, len0); } fis.close(); //得到文件内容 byte[] fileContentArr = baos.toByteArray();
注:
问:为何使用fis.read(buf) != -1判断文件是否读取完毕?
答:本来读到的是-128至127;但是在此处read已经将读取到的字节转化成了0~255; 如果不做转化,判断条件就是-129,这样子不方便记忆和理解。
4、具体实现方案
工具util类
package com.mmzs.util; /** * @author: mmzs * @date: 2018年8月9日 * @Description: * 博客地址:https://www.cnblogs.com/mmzs/p/9282412.html * @version V1.0 */ public class Util { /** * 将int转化为字节数组 * @return */ public static byte[] int2Bytes(int i){ byte[] arr = new byte[4]; arr[0] = (byte) i; arr[1] = (byte) (i >> 8); arr[2] = (byte) (i >> 16); arr[3] = (byte) (i >> 24); return arr; } /** * 将字节数组转化为int */ public static int bytes2Int(byte[] bytes){ int i0 = bytes[0]; int i1 = (bytes[1] & 0xFF) << 8; int i2 = (bytes[2] & 0xFF) << 16; int i3 = (bytes[3] & 0xFF) << 24; return i0 | i1 | i2 | i3; } }
实现归档Archiver类
package com.mmzs.archiver; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import com.mmzs.util.Util; /** * @author: mmzs * @date: 2018年8月8日 * @Description: 将多个零碎小文件归档 * 博客地址:https://www.cnblogs.com/mmzs/p/9282412.html * @version V1.0 */ public class Archiver { public static void main(String[] args) throws IOException, Exception { FileOutputStream fos = new FileOutputStream("d:/test/x.rar");
fos.write(addFile("D:/test/test.txt")); fos.write(addFile("D:/test/chart.png")); fos.write(addFile("D:/test/test.xls"));
fos.close();
System.out.println("归档完成,归档后的文件已经存放在"+"d:/test/x.rar"+"目录下"); } /** * path : d:/xxx/xxx/a.jpg * @throws Exception */ public static byte[] addFile(String path) throws Exception{ //文件 File f = new File(path); //文件名 String fname = f.getName(); //文件名数组 byte[] fnameBytes = fname.getBytes(); int fnameLen = fnameBytes.length; //文件内容长度 int fcontentLen = (int) f.length(); //计算总长度 int total = 4 + fnameLen + 4 + fcontentLen; //初始化总数组 byte[] bytes = new byte[total]; //1.写入文件名长度到总数组 byte[] fnameArr = Util.int2Bytes(fnameLen); System.arraycopy(fnameArr, 0, bytes, 0, 4); //2.写入文件名本身到总数组 System.arraycopy(fnameBytes, 0, bytes, 4, fnameLen); //3.写入文件内容长度到总数组 byte[] fcontentArr = Util.int2Bytes(fcontentLen); System.arraycopy(fcontentArr, 0, bytes, 4 + fnameLen, 4); //4.写入文件内容 //读取文件内容到字节数组中 ByteArrayOutputStream baos = new ByteArrayOutputStream(); FileInputStream fis = new FileInputStream(f); byte[] buf = new byte[1024]; int len = 0; while ((len = fis.read(buf)) != -1) { baos.write(buf, 0, len); } fis.close(); //得到转化为字节数组的文件内容,并将文件内容到总数组 byte[] fileContentArr = baos.toByteArray(); System.arraycopy(fileContentArr, 0, bytes, 4 + fnameLen + 4, fileContentArr.length); return bytes; } }
最后附一张工程截图: