• 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
    ",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");//合并后大文件的存放位置
        }
    }
  • 相关阅读:
    2017-2018-2 20179202《网络攻防技术》第一周作业
    《构建之法(第三版)》第四章
    《深入理解计算机系统(第三版)》第四章
    《文献管理与信息分析》第三章
    我们不一样
    linux centOS 7安装mysql 5.7.24
    centOS 8 使用dnf安装Docker
    centOS7服务器/dev/vda1空间100%,没有可用空间
    深刻理解 Docker 镜像大小
    使用linux docker环境打包Springboot jar包为docker镜像
  • 原文地址:https://www.cnblogs.com/huang-changfan/p/9908096.html
Copyright © 2020-2023  润新知