IO_文件分割与合并_RandomAccessFile_初始化参数_SequenceInputStreamJAVA164-167

来源:http://www.bjsxt.com/
一、S02E164_01IO_文件分割与合并_RandomAccessFile

package com.test.io.file.split0merge;

import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;

/**
 * 文件分割的思路
 * 第一步:分割的准备
 * 1、分割的块数  size    n块
 * 2、确定每一块的大小   blockSize
 *      最后一块的大小:总的文件大小-(n-1)*blockSize
 * 3、每块的名称
 * 第二步
 * 4、分割
 *  a)第几块、每块的起点、实际大小
 *  b)文件分割
 */
public class TestRandomAccessFile {
    public static void main(String[] args) throws IOException {
        RandomAccessFile raf = new RandomAccessFile(new File("G:/java/test/path.java"), "r");
        raf.seek(20);
        //定义缓冲大小
        byte[] flush = new byte[1024];
        //接收长度
        int len = 0;
        while(-1 != (len=raf.read(flush))){
            if(len >=200){
                System.out.println(new String(flush,0,200));
                break;              
            }else{
                System.out.println(new String(flush,0,len));
            }
        }
        raf.close();
    }
}

二、S02E165_01IO_文件分割与合并_初始化各项参数
三、S02E166_01IO_文件分割与合并_分割
四、S02E167_01IO_文件分割与合并_文件合并_SequenceInputStream

package com.test.io.file.split0merge;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.RandomAccessFile;
import java.io.SequenceInputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Vector;

public class SplitFile {
    //文件路径
    private String filePath;
    //文件名
    private String fileName;
    //文件大小
    private long length;
    //块数
    private int size;
    //每块的大小
    private long blockSize;
    //分割后的存放目录
    private String desBlockPath;
    //每块的名称
    private List<String> blockPath;

    public SplitFile(){
        blockPath = new ArrayList<String>();
    }
    public SplitFile(String filePath,String desBlockPath){
        this(filePath,desBlockPath,1024);
    }
    public SplitFile(String filePath,String desBlockPath,long blockSize){
        this();
        this.filePath = filePath;
        this.desBlockPath = desBlockPath;
        this.blockSize = blockSize;
        init();
    }
    /**
     * 初始化操作    计算块数、确定文件名
     */
    public void init(){
        File src = null;
        //健壮性
        if( (null==filePath) || !((src=new File(filePath)).exists()) ){
            return;
        }
        if(src.isDirectory()){
            return;
        }
        //文件名
        fileName = src.getName();
        //计算块数  实际总大小与每块大小
        length = src.length();
        //修正    每块大小超过实际总大小
        if(blockSize > length){
            blockSize = length;
        }
        //确定块数
        size = (int)Math.ceil(length*1.0/blockSize);//两整数,被除数比除数小,结果为0/解决:类型升级
        //确定每块的文件路径
        initPathName();
    }
    private void initPathName(){
        for (int i = 0; i < size; i++) {
            blockPath.add(desBlockPath + "/" + fileName + ".part" + i);
        }
    }
    /**
     * 文件的分割
     * 1、第几块
     * 2、起始位置
     * 3、实际的大小
     * @param desPath 分割文件的存放目录
     */
    public void split(){
        long beginPos = 0;//起始点
        long actualBlockSize = blockSize;//实际每块的大小
        //计算所有块的大小、位置、索引
        for (int i = 0; i < size; i++) {
            if(i == size-1){//最后一块
                actualBlockSize = length - beginPos;
            }
            splitDetail(i,beginPos,actualBlockSize);
            beginPos += actualBlockSize;
        }
    }
    /**
     * 文件的分割    输入输出
     * 文件拷贝
     * @param idx   第几块
     * @param beginPos  起始点
     * @param actualBolckSize   实际块大小
     */
    public void splitDetail(int idx,long beginPos,long actualBolckSize){
        //1、创建源
        File src = new File(filePath);//源文件
        File des = new File(blockPath.get(idx));
        //2、选择流
        RandomAccessFile raf = null;//输入流
        BufferedOutputStream bos = null;//输出流
        try {
            raf = new RandomAccessFile(src,"r");
            bos = new BufferedOutputStream(new FileOutputStream(des));
            //读取文件
            raf.seek(beginPos);
            //缓冲区
            byte[] flush = new byte[1024];
            //接收长度
            int len = 0;
            while(-1 != (len=raf.read(flush))){//一块可能一次读完,也可能分多次读完
                //System.out.println(len);
                if(actualBolckSize - len >= 0 ){//查看是否读够
                    //写出
                    bos.write(flush, 0, len);
                    actualBolckSize -= len;//剩余量
                }else{//写出最后一次的剩余量
                    bos.write(flush, 0, (int)actualBolckSize);
                    break;
                }
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }finally{
            try {
                bos.close();
                raf.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    /**
     * 文件的合并
     * @param desPath
     */
    public void mergeFile(String desPath){
        //创建源
        File des = new File(desPath);
        //选择流
        BufferedOutputStream bos = null;
        try {
            bos = new BufferedOutputStream(new FileOutputStream(des,true));//追加
            BufferedInputStream bis = null;
            for (int i = 0; i < blockPath.size(); i++) {
                bis = new BufferedInputStream(new FileInputStream(new File(blockPath.get(i))));
                byte[] flush = new byte[1024];
                int len = 0;
                while(-1 != (len=bis.read(flush))){
                    bos.write(flush, 0, len);
                }
                bis.close();
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }finally{
            try {
                bos.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    /**
     * 文件的合并
     * SequenceInputStream表示其他输入流的逻辑串联。
     * 它从输入流的有序集合开始,并从第一个输入流开始读取,直到到达文件末尾,
     * 接着从第二个输入流读取,依次类推,直到到达包含的最后一个输入流的文件末尾为止。 
     * 
     * SequenceInputStream(Enumeration<? extends InputStream> e)传入参数为枚举类型
     * <br>Enumeration<InputStream> java.util.Vector.elements()返回枚举
     * @param desPath
     */
    public void mergeFileBySequenceInputStream(String desPath){
        //创建源
        File des = new File(desPath);
        //选择流
        BufferedOutputStream bos = null;//输出流
        SequenceInputStream sis = null;//输入流
        //创建一个容器存放流
        Vector<InputStream> vi = new Vector<InputStream>();
        try {
            bos = new BufferedOutputStream(new FileOutputStream(des));

            for (int i = 0; i < blockPath.size(); i++) {
                vi.add(new BufferedInputStream(new FileInputStream(new File(blockPath.get(i)))));
            }
            sis = new SequenceInputStream(vi.elements());//SequenceInputStream(Enumeration<? extends InputStream> e)

            byte[] flush = new byte[1024];
            int len = 0;
            while(-1 != (len=sis.read(flush))){
                bos.write(flush, 0, len);
            }
            sis.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }finally{
            try {
                bos.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    /*************************************************************/
    /**
     * @param args
     */
    public static void main(String[] args) {
        SplitFile split = new SplitFile("G:/java/test/src.txt","G:/java/test",400);
        System.out.println(split.size);
        split.split();
        split.mergeFile("G:/java/test/des.txt");
        split.mergeFileBySequenceInputStream("G:/java/test/desBySequenceInputStream.txt");
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值