大数据开发之文件归档和解归档

一,归档

在大数据开发中往往要运算海量数据,可是这些数据分布在许多小文件中,传输和运算十分不方便,为此我们得进行文件归档

即把几个小文件写到一个文件中形成大文件,可是我们要怎么写呢?每个团队有每个团队的方法,下面介绍我自己的方法。

                    格式:        4个字节        文件名称的数据存储大小(n,表示存储的文件有几个字节)

                                       n个字节        文件名称

                                       4个字节        文件内容的数据存储大小(m,表示存储的文件有几个字节)

                                       m个字节        文件内容

 

                   有几个小文件,那么归档后的文件就有多少个这样的格式。

 

第一步 定义一个函数,使用4个字节,存储 文件名称的数据存储大小,归档的时候使用,看代码

public byte[] int2Bytes(int i)
    {
        byte[] arr = new byte[4];
        arr[0]=(byte)i;
        arr[1]=(byte)(i>>8);
        arr[1]=(byte)(i>>8);
        arr[1]=(byte)(i>>8);
        return arr;
    }

第2步定义一个函数,把这4个字节的二进制数据转换成我们能看懂的数据,解归档的时候用

public int Bytes2int(byte bytes[])
    {
        int i0=bytes[0] & 0xFF;     //byte类型运算时会自动转成int类型,为了防止字节数据的第一位为1而导致扩充后前面全补1导致正数变负数
        int i1 = (bytes[1] & 0xFF) << 8 ; 
        int i2 = (bytes[2] & 0xFF) << 16 ;
        int i3 = (bytes[3] & 0xFF) << 24 ;
        return i0 | i1 | i2 | i3 ;    
    }

归档代码如下

package 归档;

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

public class Archivee {

    public static void main(String[] args) throws Exception {
            FileOutputStream fos = new FileOutputStream("d:/arch/x.xar");
            fos.write(addFile("D:/arch/a.xls"));
            fos.write(addFile("D:/arch/b.xml"));
            fos.write(addFile("D:/arch/c.txt"));
            fos.close();
    }
    public static byte[] addFile(String path) throws Exception
    {
        //文件路径
        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);
        }
        fis.close();
        //得到文件内容
        byte[] fcontentArr = baos.toByteArray();
        System.arraycopy(fcontentArr, 0, bytes, 4 + fnameBytes.length + 4 , fcontentArr.length);
        return bytes;    
     }
}

 

三,解归档

首先要定义一个实体类来存储文件名称和文件内容,然后放到List集合中,然后同一写出去。

package 归档;

class FileBean {
     private String fileName;
     private byte[] fileContent;
     
     
    public FileBean() {
        
    }
    public FileBean(String fileName, byte[] fileContent) {
    
        this.fileName = fileName;
        this.fileContent = 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;
    }
     
     
}

具体代码:

package 归档;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.util.ArrayList;
import java.util.List;



public class UnArchiver {

    public static void main(String[] args)throws Exception {
        List<FileBean> files = new ArrayList<FileBean>();
        
        FileInputStream fis = new FileInputStream("d:/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("d:/arch/unarch/"+fb.getFileName());
            fos.write(fb.getFileContent());
            fos.close();
        }
    }
    
    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 fname = new String(fileNameBytes);
        
        //再读取4个字节作为文件内容的长度
        fis.read(bytes4);
        int fileContentLen = Util.Bytes2int(bytes4);
        
        //读取文件内容
        byte[] fileContentBytes = new byte[fileContentLen];
        fis.read(fileContentBytes);
        
        return new FileBean(fname,fileContentBytes);
        
    }
}

 

posted @ 2018-04-06 22:43  浅笑微凉  阅读(243)  评论(0编辑  收藏  举报