基本思路:

    文件归档,换句话就是把多个文件的字节存到一个文件中。为此我们必须定义存储格式,才能从包中把文件重新抽出来。
    文件由文件名和内容组成。要想完整的还原文件,我们必须同时存下这两个东西,而文件名和内容的字节大小我们都是不知道的,为此我们必须要用固定大小的空间存储它们的大小。

存储格式

名称 大小(单位字节)
文件名大小(fileNameLen) 1
文件名(fileName) fileNameLen
文件内容大小(fileContentLen) 4
文件内容(fileContent) fileContentLen

代码实现

因为文件内容大小是4个字节(也就是int型),我们要把它存到文件,就要转化成字节数组。我们规定低位靠前,高位靠后。按照这种格式封装转换操作与一个基础类DataUtil中。

DataUtil代码

package util;

public class DataUtil {
	public static byte[] int2bytes(int src) {
		byte[] rt = new byte[4];
		for(int i=0; i<4; ++i) {
			rt[i] = (byte)(src>>(i*8));
		}
		return rt;
	}
	public static int bytes2int(byte[] src) {
		int rt = 0;
		for(int i=0; i<4; ++i) {
			rt |= (src[i]&0xFF)<<(i*8);
			//字节在进行移位运算时,首先会被转换成int类型,
			//此时若字节的符号位为1,它前面就会补全1,比如:
			//0x80在byte类型时是-128,而转换成int,它的值还是
			//-128,即0xffffff80,而我们移位运算想要的是
			//0x00000080,即前面补全0,跟我们拆时一致。为此,
			//我们让它与0xFF相与,从0xffffff80变为0x00000080。
		}
		return rt;
	}
}

归档类

package wfb.binSama;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;

import util.DataUtil;

/**
 * @author binSama
 */
public class Archive {
	
	public static void archive(File[] srcs,File tar) {//归档
		try {
			FileOutputStream fos = new FileOutputStream(tar);
			for(int i=0; i<srcs.length; ++i) {
				//获得文件名
				byte[] fileName = srcs[i].getName().getBytes();
				//获得文件名长度
				byte fileNameLen = (byte)fileName.length;
				//获得文件内容
				FileInputStream fis = new FileInputStream(srcs[i]);
				ByteArrayOutputStream baos = new ByteArrayOutputStream();
				int len = -1;
				byte[] buf = new byte[1024];
				while((len = fis.read(buf)) != -1) {
					baos.write(buf, 0, len);
				}
				baos.close();
				fis.close();
				byte[] fileContent = baos.toByteArray();
				//获得文件内容长度
				byte[] fileContentLen = DataUtil.int2bytes(fileContent.length);
				//写入
				fos.write(fileNameLen);
				fos.write(fileName);
				fos.write(fileContentLen);
				fos.write(fileContent);
			}
			fos.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	public static void unArchive(File src) {//解档到当前文件夹
		try {
			FileInputStream fis = new FileInputStream(src);
			int fileNameLen = -1;
			while((fileNameLen = fis.read()) != -1){
				byte[] byteFileName = new byte[fileNameLen];
				fis.read(byteFileName);
				String fileName = src.getParent() +"\\"+ new String(byteFileName);
				FileOutputStream fos = new FileOutputStream(fileName);
				byte[] byteFileContentLen = new byte[4];
				fis.read(byteFileContentLen);
				int fileContentLen = DataUtil.bytes2int(byteFileContentLen);
				int divisorFileContentLen = fileContentLen / 1024;
				int remainderFileContentLen = fileContentLen % 1024;
				ByteArrayOutputStream baos = new ByteArrayOutputStream();
				byte[] divisorBuf = new byte[1024];
				for(int i=0; i<divisorFileContentLen; ++i) {
					fis.read(divisorBuf);
					baos.write(divisorBuf);
				}
				byte[] remainderBuf = new byte[remainderFileContentLen];
				fis.read(remainderBuf);
				baos.write(remainderBuf);
				baos.close();
				byte[] fileContent = baos.toByteArray();
				fos.write(fileContent);
			}
			fis.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}

测试:

package wfb.binSama;

import java.io.File;

public class Test {
	@org.junit.Test
	public void test() {
		File[] files = new File[3];
		files[0] = new File("E:\\waster\\Archiver1\\1.txt");
		files[1] = new File("E:\\waster\\Archiver1\\2.png");
		files[2] = new File("E:\\waster\\Archiver1\\3.txt");
		File bsm = new File("E:\\waster\\Archiver2\\archive.bsm");
		Archive.archive(files, bsm);
		Archive.unArchive(bsm);
	}
	
}

现象

成功在E:\waster\Archiver2文件夹生成了archive.bsm归档文件,并解档出1.txt 2.png 3.txt三个文件。
E:\waster\Archiver2文件


版权声明:本文为qq_40424244原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
原文链接:https://blog.csdn.net/qq_40424244/article/details/82874160