原创

Java复习之-随机流实例-文件分割

1.面向过程的分割文件编程(使用多线程时,再优化此功能)

/**
 * Created by 18877 on 2019/8/21.
 * 随机读取和写入流
 * 文件分割
 * 基础框架雏形
 */
public class ContentEncode {
    public static void main(String[] args) throws IOException {
        //分多少块
        File src = new File("D:\\","测试目录\\test.txt");
        //先获取文件的总长度
        long len = src.length();
        //指定每次读取的块大小
        int blockSize = 3;
        int size = (int) Math.ceil(len*1.0/blockSize);//向上取整

        int beginPos = 0;//起始点
        int actualSize = (int)(blockSize>len?len:blockSize);//如果读取的大小比文件大,则直接读取整个文件,否则为指定大小

        for(int i=0;i<size;i++){
            beginPos = i*blockSize;//读取点(读取的位置)
            if (i==size-1){//如果是最后一块,直接读取文件剩余大小
                actualSize = (int) len;
            }else {
                actualSize = blockSize;//每块大小
                len -= actualSize;//总文件大小-读取过的大小=剩下的大小
            }
            System.out.println(i+"-->"+beginPos+"-->>"+actualSize);
            split(i,beginPos,actualSize);//调用主要分割业务
        }

    }

    public static void split(int i,int beginPos,int actualSize) throws IOException {
        RandomAccessFile raf = new RandomAccessFile(new File("D:\\","测试目录\\test.txt"),"rw");
//        int beginPos = 0;//起始读取位置
//        int actualSize = 3;//实际大小(每次要读取的大小)

        //随机读取
        raf.seek(beginPos);//UTF-8的每个中文占3个字节


        //分段读取
        byte[] flush = new byte[1024];
        int len = -1;
        while ((len=raf.read(flush))!=-1){
            if (actualSize>len){//如果要获取的大小比文件大,就直接获取文件大小
                System.out.println(new String(flush,0,len));
                actualSize -= len;//剩余需要实际大小多少,实际大小-读取过的
                System.out.println(actualSize);
            }else {
                System.out.println(new String(flush,0,actualSize));//输出指定大小读取到的内容
                break;
            }
        }
        raf.close();
    }
}

2.使用面向对象编程优化

/**
 * Created by 18877 on 2019/8/21.
 * 随机读取和写入流
 * 文件分割
 * 面向对象思想分割
 */
public class ContentEncode1 {
    //源头
    private File src;
    //目的地(文件夹)
    private String destDir;
    //所有分割后的文件存储路径
    private List<String> destPaths;
    //每块大小
    private int blockSize;
    //多少块
    private int size;

    public ContentEncode1(String srcPath, String destDir, int blockSize) {
        this.src = new File(srcPath);
        this.destDir = destDir;
        this.destPaths = new ArrayList<>();
        this.blockSize = blockSize;
        init();
    }
    private void init(){
        //先获取文件的总长度
        long len = this.src.length();
        this.size = (int) Math.ceil(len*1.0/blockSize);//向上取整

        //路径
        for (int i=0;i<size;i++){
            this.destPaths.add(this.destDir+"\\"+i+"-"+this.src.getName());
        }
    }

    public void split() throws IOException {
        //先获取文件的总长度
        long len = src.length();
        int beginPos = 0;//起始点
        int actualSize = (int)(blockSize>len?len:blockSize);//如果读取的大小比文件大,则直接读取整个文件,否则为指定大小

        for(int i=0;i<size;i++){
            beginPos = i*blockSize;//读取点(读取的位置)
            if (i==size-1){//如果是最后一块,直接读取文件剩余大小
                actualSize = (int) len;
            }else {
                actualSize = blockSize;//每块大小
                len -= actualSize;//总文件大小-读取过的大小=剩下的大小
            }
            splitDetail(i,beginPos,actualSize);//调用主要分割业务
        }
    }

    public static void main(String[] args) throws IOException {
            ContentEncode1 encode1 = new ContentEncode1("D:\\测试目录\\split.png","D:\\测试目录\\sp",1024);
            encode1.split();
    }

    private void splitDetail(int i,int beginPos,int actualSize) throws IOException {
        RandomAccessFile raf = new RandomAccessFile(this.src,"rw");
        RandomAccessFile raf2 = new RandomAccessFile(this.destPaths.get(i),"rw");

        //随机读取
        raf.seek(beginPos);//UTF-8的每个中文占3个字节


        //分段读取
        byte[] flush = new byte[1024];
        int len = -1;
        while ((len=raf.read(flush))!=-1){
            if (actualSize>len){//如果要获取的大小比文件大,就直接获取文件大小
                raf2.write(flush,0,len);
                actualSize -= len;//剩余需要实际大小多少,实际大小-读取过的
            }else {
                raf2.write(flush,0,actualSize);
                break;
            }
        }
        raf.close();
        raf2.close();
    }
}

3.合并文件

encode1.merge("D:\\测试目录\\split1.png");//main方法调用
//类中添加合并方法
public void merge(String destPath) throws IOException {
        //输出流
        OutputStream os = new BufferedOutputStream(new FileOutputStream(new File(destPath),true));
        //输入流
        for (int i=0;i<destPaths.size();i++){
            InputStream is = new BufferedInputStream(new FileInputStream(destPaths.get(i)));

            byte[] flush = new byte[1024];
            int len = -1;
            while ((len=is.read(flush))!=-1){
                os.write(flush,0,len);
            }
            os.flush();
            is.close();
        }
        os.close();
    }

4.使用SequenceInputStream类合并输入流

public void merge(String destPath) throws IOException {
        //输出流
        OutputStream os = new BufferedOutputStream(new FileOutputStream(new File(destPath),true));
        Vector<InputStream> vi = new Vector<>();//容器
        SequenceInputStream sis = null;
        //输入流
        for (int i=0;i<destPaths.size();i++){
            vi.add(new BufferedInputStream(new FileInputStream(destPaths.get(i))));
        }
        sis = new SequenceInputStream(vi.elements());
        byte[] flush = new byte[1024];
        int len = -1;
        while ((len=sis.read(flush))!=-1){
            os.write(flush,0,len);
        }
        os.flush();
        sis.close();
        os.close();
    }
java
  • 作者:兰总(联系作者)
  • 发表时间:2019-08-22 00:52
  • 版权声明:自由转载-非商用-保持署名
  • 公众号转载:请在文末添加作者公众号二维码
  • 评论