hadoop中如日志文件、天气记录文档等都是以文档的形式储存数据。而大量存储文档,就会涉及到将有共同特点或者相似性的文档归为一类等(如按照年份将相同年份的天气数据文档归为一类)。
从而需要我们对文档的归档和解档有一定了解。
归档就是将多个有共同点的文档归为一个大的文档;解档就是将一个大文档,分解成多个独立的文档。
这里先普及一下基础:多个文档归为一个时,需要确定文档名称、文档内容,定义文档名称长度、文档内容长度。顺序是定义好文档名称长度,往里面写名称,在定义好文档内容长度,往里面加文档内容,然后下一个文档加在这个文档后面步骤和上一个文档一样。
解档就是归档的逆推。
下面废话不多说直接上程序
首先是类型转换工具类就是我上一章的内容
**
* @ClassName Util
* @Decription 类型转换工具类
* @Author AlexZ
* @Date 2018-8-1 14:17
* @Version 1.0
*/
public class Util {
/**
* 整型转换成字节数组
*/
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] & 0xFF;
int i1 = (bytes[1] & 0xFF) << 8;
int i2 = (bytes[2] & 0xFF) << 16;
int i3 = (bytes[3] & 0xFF) << 24;
return i0 | i1 | i2 | i3;
}
}
然后是文档的归档器
import java.io.*;
/**
* @ClassName Arcchiver
* @Decription 归档器
* @Author AlexZ
* @Date 2018-8-1 13:57
* @Version 1.0
*/
public class Arcchiver {
public static void main(String[] args) throws Exception{
//
FileOutputStream fos = new FileOutputStream("g:/arch/x.xar",true);
fos.write(addFile("G:/arch/a.xls"));
fos.write(addFile("G:/arch/b.java"));
fos.close();
//
}
/**
* path : g:/xxx/xxx/a.jpg
*/
public static byte[] addFile(String path) throws IOException{
//文件
File f = new File(path);
//文件名
String fname = f.getName();
//文件名数组
byte[] fnameBytes = fname.getBytes();
//文件内容长度
int len = (int)f.length();
//计算总长度
int total = 4 + fnameBytes.length + 4 +len ;
//初始化总数组
byte[] bytes = new byte[total];
//1.写入文件名长度
byte[] fnameLenArr = Util.int2Bytes(fnameBytes.length);
System.arraycopy(fnameLenArr,0, bytes,0,4);
//2.写入文件名本身
System.arraycopy(fnameBytes,0, bytes,4, fnameBytes.length);
//3.写入文件内容长度
byte[] fcontentLenArr = Util.int2Bytes(len);
System.arraycopy(fcontentLenArr,0,bytes,4+fnameBytes.length, 4);
//4.写入文件内容本身
//读取文件内容到数组中
ByteArrayOutputStream baos = new ByteArrayOutputStream();
FileInputStream fis = new FileInputStream(f);
byte[] buf = new byte[1024];
int len0 = 0;
while ((len0 = fis.read(buf)) != -1){
baos.write(buf,0,len0);
}
//得到文件内容
byte[] fileContentArr = baos.toByteArray();
System.arraycopy(fileContentArr,0 ,bytes,8 + fnameBytes.length, fileContentArr.length);
return bytes;
}
}
最后是解析器
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.util.ArrayList;
import java.util.List;
/**
* @ClassName Unarchiver
* @Decription 解析器
* @Author AlexZ
* @Date 2018-8-1 17:09
* @Version 1.0
*/
public class Unarchiver {
public static void main(String[] args) throws Exception{
List<FileBean> files = new ArrayList<FileBean>();
//
FileInputStream fis = new FileInputStream("g:/arch/x.xar");
FileBean fileBean = null;
//
while ((fileBean = readNextFile(fis)) != null) {
files.add(fileBean);
}
//关闭流
fis.close();
FileOutputStream fos = null;
//
for (FileBean fb : files){
fos = new FileOutputStream("g:/arch/unarch/"+fb.getFileName());
fos.write(fb.getFileContent());
fos.close();
}
}
/**
* 从流中读取下一个文件
* @param fis
* @return
*/
public static FileBean readNextFile(FileInputStream fis) throws Exception{
//
byte[] bytes4 = new byte[4];
//读取四个字节
int res = fis.read(bytes4);
if (res == -1){
return null;
}
//文件名长度
int fnameLen = Util.bytes2Int(bytes4);
//文件名数组
byte[] fileNameBytes = new byte[fnameLen];
fis.read(fileNameBytes);
//得到文件名
String fileName = new String(fileNameBytes);
//在读取4个字节,作为文件内容长度
fis.read(bytes4);
int fileContLen = Util.bytes2Int(bytes4);
//读取文件内容
byte[] fileContBytes = new byte[fileContLen];
fis.read(fileContBytes);
return new FileBean(fileName,fileContBytes);
}
}
最后是中间用到的FileBean类
/**
* @ClassName FileBean
* @Decription 文件Bean
* @Author AlexZ
* @Date 2018-8-1 20:02
* @Version 1.0
*/
public class FileBean {
private String fileName;
private byte[] fileContent;
public String getFileName() {
return fileName;
}
public void setFileName(String fileName) {
this.fileName = fileName;
}
public byte[] getFileContent() {
return fileContent;
}
public void setFileContent(byte[] fileContent) {
this.fileContent = fileContent;
}
public FileBean(){
}
public FileBean(String fileName, byte[] fileContent) {
this.fileName = fileName;
this.fileContent = fileContent;
}
}