文件分割与合并(Java)

一、文件分割示意图

二、文件合并示意图

方式一:通过文件追加的方式

方式二:通过SequenceInputStream对其他输入流的逻辑串联。

测试RandomAccessFile随机访问文件

package FileSplitMerge;

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

import IOOthers.FileUtil;

/**
 * RandomAccessFile
 * 此类的实例支持对随机访问文件的读取和写入。
 *
 * 文件分割的思路
 * 1、 分割的块数 size   n块
 * 2、 每一块的大小 blocksize
 *    最后一块:总的文件大小-(n-1)*blockSize
 */

public class Demo01 {
    public static void main(String[] args) throws IOException {
        RandomAccessFile rnd = new RandomAccessFile(new File("G:/writer.txt"), "r");
        //UTF-8-->英文使用1个字节,中文使用3个字节来编码
        //GBK-->每个字符占用2个字节
        //从第12个读起       这是采用的是UTF-8
        rnd.seek(12);
        //定义缓冲大小
        byte[] flush = new byte[1024];
        //接收长度
        int len=0;

        while(-1!=(len=rnd.read(flush)))
        {
            if(len>=48)
            {
                System.out.println(new String(flush,0,48));
            }
            else {
                System.out.println(new String(flush,0,len));
            }
        }
        FileUtil.close(rnd);
    }
}

运行结果:

都有青春,
每个青春都有一个故事?
re ESX资源管理与性能优化
S1.1.11VMware
??FT-Practise
实验演示7:vApp-Practise
?

文件的分割与合并

package FileSplitMerge;

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;

import IOOthers.FileUtil;

@SuppressWarnings("all")
public class SplitFile {

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

    public SplitFile() {
        blockPath = new ArrayList<String>() ;
    }
    public SplitFile(String filePath,String destBlockPath) {
        this(filePath,1024, destBlockPath);
    }

    public SplitFile(String filePath, long blocksize,String destBlockPath) {
        this();
        this.filePath = filePath;
        this.destBlockPath = destBlockPath;
        this.blocksize = blocksize;
    }

    /**
     * 初始化操作 计算块数、确定文件名
     */
    public void init()
    {
        File src = null;
        //健壮性    创建成功就会得到构造方法初始化的值
        if(null==filePath || !(src=new File(filePath)).exists())
        {
            return;
        }
        if(src.isDirectory())
        {
            return;
        }

        //文件名    g:/writer.txt的 writer.txt
        this.fileName = src.getName();
        //文件的大小
        this.length = src.length();

        //修正    每块的大小
        if(this.blocksize>length) //如果每块的大小大于文本的长度,则每块的大小=长度
        {
            this.blocksize = length;
        }

        //确定块数        ceil最小(最接近负无穷大)浮点值,该值大于等于该参数,并等于某个整数。
        size = (int) Math.ceil(length*1.0/this.blocksize);

        //确定文件的路径
        initPathName();
    }

    private void initPathName()
    {
        for(int i=0;i<size;i++)
        {
            //List容器里面增加每一块的路径
            this.blockPath.add(destBlockPath+"/"+this.fileName+".part"+i);
        }
    }

    /**
     * 文件分割
     * 确定在第几块
     * 1、起始位置
     * 2、实际大小
     * @param destPath 分割文件存放目录
     * @throws IOException
     */
    public void split(String destPath) throws IOException
    {
        //确定文件的路径
        //每一块的名称
        //initPathName(destPath);
        long beginPos = 0;//起始点
        long actualBlockSize = blocksize;//实际大小
        //计算所有快的大小、位置、索引
        for(int i=0;i<size; i++)
        {
            if(i == size-1)
            {
                //最后一块
                actualBlockSize = this.length-beginPos;
            }
            //具体分割方法     第几块    起始分割地址        实际的块大小
            splitDetail(i,beginPos,actualBlockSize);
            beginPos += actualBlockSize;//本次的终点,下一次的起点
        }
    }

    /**
     * 文件分割  输入 输出
     * 文件拷贝
     * @param idx 第几块
     * @param beginPos 起始点
     * @param actualBlockSize 实际大小
     * @throws IOException
     */
    public void splitDetail(int idx,long beginPos,long actualBlockSize) throws IOException
    {
        //1、创建源
        File src = new File(this.filePath);//源文件
        //得到第几块的路径       List容器取出块路径
        File dest = new File(this.blockPath.get(idx));//目标文件

        //2、选择流
        RandomAccessFile raf = null;//输入流
        BufferedOutputStream bos = null;//输出流
        try
        {
             raf = new RandomAccessFile(src, "r");
             bos = new BufferedOutputStream(new FileOutputStream(dest));
             //3、读取文件
             raf.seek(beginPos);
             //4、缓冲区
             byte[] flush = new byte[1024];
             int len = 0;
             while(-1!=(len=raf.read(flush)))
             {
                 //写出
                 if(actualBlockSize-len>=0)//判断是否足够
                 {
                     bos.write(flush,0,len);//写出
                     actualBlockSize -= len;//剩余量
                 }
                 else
                 {
                     //读取每一块实际大小的最后一小部分   最后一次写出
                     bos.write(flush,0,(int)actualBlockSize);
                     break;//每个block最后一部分读取完之后,一定要break,否则就会继续读取
                 }
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
        finally{
            FileUtil.close(bos,raf);
        }
    }

    /**
     * 文件的合并   (方法一)
     */
    public void merge1(String destPath)
    {
        //创建源
        File dest = new File(destPath);
        //选择流
        BufferedOutputStream bos = null;//输出流
        BufferedInputStream bis = null;//输入流
        try {
            bos = new BufferedOutputStream(new FileOutputStream(dest,true));//表示追加

            for(int i=0; i<this.blockPath.size();i++)
            {
                //读取
                bis = new BufferedInputStream(new FileInputStream
                        (new File(this.blockPath.get(i))));
                //缓冲区
                byte[] flush = new byte[1024];
                //接收长度
                int len = 0;
                while(-1 !=(len = bis.read(flush)))
                {
                    //打印到控制台
                    //System.out.println(new String(flush,0,len));
                    bos.write(flush,0,len);
                }
                bos.flush();
                FileUtil.close(bis);
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        finally
        {
            FileUtil.close(bos);
        }
    }

    /**
     * 文件的合并  (方法二)
     */
    public void merge(String destPath) throws IOException
    {
        //1、创建源
        File dest = new File(destPath);

        //2、选择流
        //SequenceInputStream 表示其他输入流的逻辑串联。它从输入流的有序集合开始,
        //并从第一个输入流开始读取,直到到达文件末尾,接着从第二个输入流读取,依次类推,
        //直到到达包含的最后一个输入流的文件末尾为止。 

        SequenceInputStream sis = null;//输入流
        BufferedOutputStream bos = null;//输出源   

        //创建一个容器
        Vector<InputStream> vi = new Vector<InputStream>();
        for(int i=0; i<this.blockPath.size();i++)
        {
            vi.add(new BufferedInputStream(
                    new FileInputStream(new File(this.blockPath.get(i)))));
        }
        //SequenceInputStream sis = new SequenceInputStream(vi.elements());
        bos = new BufferedOutputStream(new FileOutputStream(dest,true));//表示追加
        sis = new SequenceInputStream(vi.elements());

        //缓冲区
        byte[] flush = new byte[1024];
        //接收长度
        int len = 0;
        while(-1 !=(len = sis.read(flush)))
        {
            //打印到控制台
            //System.out.println(new String(flush,0,len));
            bos.write(flush,0,len);
        }
        bos.flush();
        FileUtil.close(sis);
    }

    public static void main(String[] args) {
        //源文件路径、每块的大小(字节数)、目标快的路径
        SplitFile split = new SplitFile("g:/writer.txt",100,"g:/try");

        //文件初始化
        split.init();

        //文件分割
        try {
            //split.split("g:/try");
            split.split(split.destBlockPath);
        } catch (IOException e) {
            e.printStackTrace();
        }

        //文件合并
        try {
            split.merge("g:/try/test.txt");
        } catch (IOException e) {
            e.printStackTrace();
        }
        //System.out.println(file.size);
    }
}
时间: 2024-11-05 12:07:17

文件分割与合并(Java)的相关文章

java:快速文件分割及合并

文件分割与合并是一个常见需求,比如:上传大文件时,可以先分割成小块,传到服务器后,再进行合并.很多高大上的分布式文件系统(比如:google的GFS.taobao的TFS)里,也是按block为单位,对文件进行分割或合并. 看下基本思路: 如果有一个大文件,指定分割大小后(比如:按1M切割) step 1: 先根据原始文件大小.分割大小,算出最终分割的小文件数N step 2: 在磁盘上创建这N个小文件 step 3: 开多个线程(线程数=分割文件数),每个线程里,利用RandomAccessF

java文件分割和合并

package search; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.RandomAccessFile; import java.nio.ByteBuffer; import java.nio.channels.FileChannel; public class Split {

(转)java:快速文件分割及合并

文件分割与合并是一个常见需求,比如:上传大文件时,可以先分割成小块,传到服务器后,再进行合并.很多高大上的分布式文件系统(比如:google的GFS.taobao的TFS)里,也是按block为单位,对文件进行分割或合并. 看下基本思路: 如果有一个大文件,指定分割大小后(比如:按1M切割) step 1: 先根据原始文件大小.分割大小,算出最终分割的小文件数N step 2: 在磁盘上创建这N个小文件 step 3: 开多个线程(线程数=分割文件数),每个线程里,利用RandomAccessF

c语言文件分割与合并

一.综述 c语言操作文件通过文件指针FILE*,每个要操作的文件必须打开然后才能读写. 注意事项: @1分割与合并文件最好使用二进制模式即"rb"或"wb",这样可以操作任何类型文件 @2FILE 指针一定要进行判空操作即看F == NULL成立不 @3文件用完必须关闭,释放系统资源,因为文件会分配缓冲区,占据内存 1.包含头文件 _CRT_SECURE_NO_WARNINGS表示关闭安全检查 1 #define _CRT_SECURE_NO_WARNINGS 2

源码:windows文件分割与合并

#include <Windows.h> #include <vector> #include <string> using namespace std; //判断文件是否存在 bool FileExistsW(const wstring &fn) { WIN32_FIND_DATAW fd; HANDLE hFile = FindFirstFileW(fn.c_str(),&fd); if (hFile != INVALID_HANDLE_VALUE)

python学习——大文件分割与合并

在平常的生活中,我们会遇到下面这样的情况: 你下载了一个比较大型的游戏(假设有10G),现在想跟你的同学一起玩,你需要把这个游戏拷贝给他. 然后现在有一个问题是文件太大(我们不考虑你有移动硬盘什么的情况),假设现在只有一个2G或4G的优盘,该怎么办呢? 有很多方法,例如winrar压缩的时候分成很多小卷,这里不累述. 在学习python之后,我们自己就可以解决这个问题啦. 我们可以自己写一个脚本去分割合并文件,将文件分割成适合优盘大小的小文件,在拷贝,然后再合并. 下面是文件分割脚本: 1 im

c# 文件分割与合并

工作中遇到要上传下载的功能,而中间接收的服务器最大只能接收200M的文件,对于大文件无法满足,所以只能在上传的时候对大于100M的文件进行分割,分割成的小文件为原大文件名+.temp+i.在下载端,下载完成后再对其进行合并. 思路:文件的分割与合并就是将文件先转换成流再对其进行操作. /// <summary> /// 分割文件方法 /// </summary> /// <param name="filePath">被分割文件</param&g

delphi 文件分割与合并

流的使用分割与合并文件的函数 unit Unit1; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls; type TForm1 = class(TForm) Button1: TButton; Button2: TButton; procedure Button1Click(Sender: TObject); procedure

PHP大文件存储示例,各种文件分割和合并(二进制分割与合并)

最近要对视频进行上传,由于涉及到的视频非常的大,因此采用的是分片上传的格式,下面是一个简单的例子: split.php 1 <?php 2 $i = 0; //分割的块编号 3 $fp = fopen("abc.wmv","rb"); //要分割的文件 4 $file = fopen("split_hash.txt","a"); //记录分割的信息的文本文件 5 while(!feof($fp)) 6 { 7 $hand