6.6(java学习笔记)文件分割(IO综合例子)

基本思路:

文件分割:将一个文件分割成若干个独立的文件。

       设置分割后小文件文件的字节数,然后读取被分割文件,

     将对应的字节数写入分割后的小文件中。

        使用seek定位下一次读取位置。

     

文件合并:将分割后的若干的文件合并成一个完整的文件。

     按照原有分割顺序逐个读取分割后的小文件,

     然后以追加的方式写入合并的文件中。

 

读取被分割文件将指定字节数写入分割后小文件时,下一次读取时要确保当前读取位置是上一次的写入的终点。

例如文件有5000K,设置分割后的文件大小1000K,那么第一次从0开始读取1000K写入小文件1,第二次就要从1000开始读取1000K写入小文件2.

这时就需要用到seek()不断设置文件读取位置。

 

seek是RandomAccessFile类中的函数

构造方法,mode为设置读写方法,“”r“为只读”w”为只写。

 

 

设置文件指针偏移量,下一次读或写时,从当前设置的位置开始。

read,write方法与输入输出流函数相同。

 

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.OutputStream;
import java.io.RandomAccessFile;
import java.util.ArrayList;
import java.util.List;

public class FileSplit {
    private String filePath;//文件路径
    private long blockSize;//每一块大小
    private int blockNum;//块个个数
    private List<String> blockName;//每一块名称
    private String [] name;
    public FileSplit(){
        this.blockName = new ArrayList<String>();
    }
    
    public FileSplit(String filePath){
        this(filePath,1024);//未知的尺寸则默认1024
    }
    public FileSplit(String filePath, long blockSize){
        this();
        this.filePath = filePath;
        this.blockSize = blockSize;
        init();
    }
    
    
    
    public String getFilePath() {
        return filePath;
    }

    public void setFilePath(String filePath) {
        this.filePath = filePath;
    }

    public long getBlockSize() {
        return blockSize;
    }

    public void setBlockSize(long blockSize) {
        this.blockSize = blockSize;
    }

    public int getBlockNum() {
        return blockNum;
    }

    public void setBlockNum(int blockNum) {
        this.blockNum = blockNum;
    }

    public List<String> getBlockName() {
        return blockName;
    }

    public void setBlockName(List<String> blockName) {
        this.blockName = blockName;
    }

    private void initBlockName(String destPath){
        name = new File(filePath).getName().split("\\.");
        for(int i = 0; i < blockNum; i++){
            blockName.add(i,destPath + "\\" + name[0] + "_" + i + "." +name[1]);
        }
    }
    
    public void init(){
        File src = new File(filePath);
        //路径名不存在,或该路径表示的文件不存,或是文件夹在则结束。
        if(filePath == null || !src.exists()||src.isDirectory()){
            return;
        }
        if(blockSize >= src.length())
            this.blockSize = src.length();
        this.blockNum = (int)Math.ceil(src.length()*1.0/blockSize);
        
    }
    //destPath分割文件存放目录
    public void split(String destPath){//分割函数
        initBlockName(destPath);//初始化分割后的文件名
        long start = 0;
        for(int i = 0; i < blockNum; i++){
            if(i == blockNum - 1)//计算最后一块大小
                blockSize = new File(filePath).length()%blockSize;
            split_m(i,start,blockSize);//参数含义:第i块,读取位置,读取内容大小
            start += blockSize;//更新起始位置
        //    System.out.println(start);
        }
    }
    
    //开始分割,每次分割一块
    private void split_m(int blockNum,long start,long blockSize){
        int len = 0;
        byte[] flush = new byte[1024];
        RandomAccessFile raf = null;//源文件
        BufferedOutputStream bos = null;//分割后文件
        try {
            bos = new BufferedOutputStream(new FileOutputStream(new File(blockName.get(blockNum))));
            raf = new RandomAccessFile(new File(filePath),"r");
            try {
                raf.seek(start);//确定读取位置
                while(-1 != (len = raf.read(flush))){//当前块分割完成或文件已读取完跳出循环。
                    //System.out.printf("%d %d %d %s\n",start,blockSize,len,blockName.get(blockNum));
                    if((blockSize - len) >=0){//当前块大小-写入字节数,判断剩余字节
                        bos.write(flush,0,len);//如果块剩余大小大于读取字节数,则写入读取字节数
                        blockSize -= len;
                    }else{//如果小于,则写入当前块剩余字节数
                        bos.write(flush, 0, (int)blockSize);
                        break;//分块文件已写满,跳出当前循环
                    }
                }
                bos.flush();
                bos.close();
                raf.close();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            } catch (FileNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
    
    public void Merge(String mergePath){//合并文件夹路径
        int len;
        byte[] flush = new byte[1024];
        InputStream is = null;
        OutputStream bos = null;
        for(int i = 0; i < blockNum; i++){
            try {
                //每次将一个分割后的文件写入合并文件中。
                //写入方法为追加
                bos = new BufferedOutputStream(new FileOutputStream(new File(mergePath,"merge." + name[1]),true));
                is = new BufferedInputStream(new FileInputStream(new File(blockName.get(i))));
                while(-1 != (len = is.read(flush))){//直到被分割的单个小文件读取完
                    is.read(flush);//将读取内容放入flush
                    bos.write(flush,0,len);//将读取内容写入文件。
                }
                bos.flush();
                bos.close();
                is.close();//释放当前资源,下次读取下一个小文件。
            } catch (FileNotFoundException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
        
    }
}
public class Main {
    public static void main(String[] args){
        FileSplit f = new FileSplit("F:\\依风\\Desktop\\temp.txt",500);//被分割文件,分割后的字节数
        f.split("F:\\依风\\Desktop");//分割后小文件的存放位置
        f.Merge("F:\\依风\\Desktop");//合并后大文件的存放位置
    }
}

转载于:https://www.cnblogs.com/huang-changfan/p/9908096.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值