RandomAccessFile分割、还原文件(一)

RandomAccessFile
placeholder image
admin 发布于:2015-12-10 17:45:50
阅读:loading

背景介绍

想写个例子去分割大文件已经很久了,由于一些问题始终没有搞明白,故一直没去做,然而今天还是艰难的下手了,实现了这个功能示例,并且稍微完善了一下,基于RandomAccessFile随机读取文件,分割、还原文件等动作。本篇文章主要关注一下一个简单版本的分割文件、合并文件的核心模块处理逻辑,目的在于像我一样渣渣水平的人可以从基础入门,对于一些运算逻辑太复杂,或者是封装的太深的代码不太容易对于这块儿的新手儿来理解,所以本篇我重点在于精简代码,并给出相关的注释,在异常的处理上就放宽松点吧,文件的分割网上示例非常多,我理解的文件分割与我们数据库的数据分页原理类似,都是获取到总记录数total,再根据每页显示数据条数pageSize,先得出一共有多少页totalPage,再从1开始循环至totalPage,将每页的数据读取出来,而文件分割是一样的,只不过是将每页的字节单独存储为一个文件,参考代码如下:

代码实现

1.文件分割

package com;

import java.io.File;

import java.io.FileOutputStream;

import java.io.IOException;

import java.io.RandomAccessFile;

 

/**

 * 按指定文件大小分割文件

 * @author chendd

 */

public class SplitFileCore {

 

    private long  blockLength;// 分割单个文件大小

    private long currentTotal;// 当前分割次数的位置

 

    public SplitFileCore(int blockLength) {

        this.blockLength = blockLength;

    }

 

    public void split(File srcFile, String splitFolder) throws Exception {

        long fileLens = srcFile.length();// 文件大小

        if (fileLens <= this.blockLength) {

            System.out.println("分割的文件大小 " + this.blockLength + 大于文件的大小!");

            return;

        }

        RandomAccessFile raf = new RandomAccessFile(srcFile, "r");

        // 根据分割块大小,计算一共有多少块文件

        int blockCount = (int) (fileLens % this.blockLength);

        if (blockCount == 0) {

            blockCount = (int) (fileLens / this.blockLength);

        } else {

            blockCount = (int) (fileLens / this.blockLength) + 1;

        }

        // 按快进行读取文件

        String srcFileName = srcFile.getName();

        for (int i = 0; i < blockCount; i++) {

            File destFile = new File(splitFolder + File.separator + srcFileName

                    + "." + (i + 1) + ".part");

            splitFileDetail(destFile, raf);// 分割文件

        }

 

        if (raf != null) {

            raf.close();

        }

    }

 

    private void splitFileDetail(File destFile, RandomAccessFile raf)

            throws IOException {

        byte b[] = new byte[1024];

        int lens = 0;

        // 如果文件目录不存在,则创建

        if (destFile.getParentFile().exists() == false) {

            destFile.getParentFile().mkdirs();

        }

        raf.seek(currentTotal);// 设置开始读取的位置

        long currentMax = raf.getFilePointer() + this.blockLength;

        BufferedOutputStream bos = new BufferedOutputStream(

                new FileOutputStream(destFile));

        while ((lens = raf.read(b)) != -1) {

            // 判断文件读取的大小,避免已经读取超过每块的大小了

            if (currentTotal + lens > currentMax) {

                break;

            }

            bos.write(b, 0, lens);

            currentTotal += lens;// 累加读取的文件数据

        }

        if (bos != null) {

            bos.flush();

            bos.close();

        }

    }

 

    public static void main(String[] args) throws Exception {

 

        File srcFile = new File("d:\\splitFolder\\中国政区2500.jpg");

        String splitFolder = "d:\\splitFolder";// 分割存储路径

        SplitFileCore splitFile = new SplitFileCore(1024 * 1024);// 1M的大小去分割文件

        splitFile.split(srcFile, splitFolder);

        System.out.println("文件分割完毕...");

    }

 

}

2.文件合并

package com;

import java.io.BufferedOutputStream;

import java.io.File;

import java.io.FileInputStream;

import java.io.FileOutputStream;

import java.io.IOException;

import java.io.InputStream;

 

/**

 * 合并文件

 * @author chendd

 */

public class MergeFileCore {

 

    public static void main(String[] args) throws IOException,

            ClassNotFoundException {


        String propFile = "d:\\splitFolder";

        File file = new File(propFile);

        File files[] = file.listFiles();

        BufferedOutputStream bos = new BufferedOutputStream(

                new FileOutputStream(propFile + File.separator + "还原文件.jpg",

                        true));

        byte b[] = new byte[1024];

        // 循环读取文件

        for (File f : files) {

            if (f.getName().endsWith(".part") == false) {

                continue;

            }

            InputStream is = new FileInputStream(f);

            int lens = 0;

            while ((lens = is.read(b)) != -1) {

                bos.write(b, 0, lens);

            }

            is.close();

        }

        bos.flush();

        bos.close();

        System.out.println("文件还原完毕");

    }

 

}

运行结果

运行结果示例.jpg

至此,分割一个二进制的文件是没有问题的,至于前文中所说的没想明白的问题,其实是分割字符文件时,按由于是按字节进行分割,如果遇到中文字符会出现字符被截取的不完整,乱码的问题,这个问题后来参考了一些意见:

1)分割文件不等于时文件分段读取;

2)有乱码不要紧,再合并文件时就正常了;

3)或许按行读取文件的方式可以一试。

 点赞


 发表评论

当前回复:作者

 评论列表


留言区