利用IO流对文件进行分割和无损还原合并

1、实现原理分布写在注释里,基本思路是将源文件分割为若干份,之后再将分割的文件进行合并还原。

2、实现代码如下:


package com.tiger.copy.split.combine;

import java.io.*;
/**
 * 文件的分割与合并
 * @author tiger
 * @Date 2017年7月21日
 */
public class FileSplitAndCombine {
	/*
	 * 测试
	 */
	public static void main( String[] args ) 
			throws IOException {
		String cPath = "E:\\tigerFolder\\J2SE6.0 API(冷冬大雪).chm";
		String sPath = "E:\\tigerFolder\\split";
		fileSplit(cPath,sPath,9,1024,"chm");
		/*================================================================*/
//		String srcPath = "E:\\tigerFolder\\split";
//		String destPath = "E:\\tigerFolder\\combine.chm";
//		fileCombine(srcPath,destPath,9,1024,".chm");
		
	}
	/**
	 * 文件的切割
	 * @param srcPath 切割源文件路径
	 * @param destPath 合并文件路径
	 * @param size 切割块数
	 * @param speed 切割速度
	 * @param suffix 切割文件后缀
	 * @throws IOException 异常处理
	 */
	public static void fileSplit(String srcPath,String destPath,
	int size,int speed,String suffix) throws IOException{
		long start = System.currentTimeMillis();
		InputStream is = new FileInputStream( srcPath );
		//获取文件可读取的字节数,依据这个对文件进行分割
		int total = is.available();
		//文件分块切割数目 size,余数放到最后一个文件中。
		int[] blocks = new int[size];
		for (int i = 0; i < size; i++) {
			if (i == size - 1) {
				blocks[i] = total/size + total%size;
			}else {
				blocks[i] = total/size;
			}
		}
		//定义创建 size 个输出流的数组.
		OutputStream[] outs = new OutputStream[ size ];
		for (int i = 0; i < outs.length; i++) {
			outs[i] = new FileOutputStream( destPath + i + suffix);
		}

		int index = 0; 
		//表示要读取到哪一块,一块一块地读取
		int remain = blocks[ index ];
		//记录当次需要读取多少个字节
		int needRead;   
		int len = 0;
		byte[] buff = new byte[speed];
		while( index < size ){
			//处理数组越界问题
			if( remain > speed ){
				needRead = speed;
			}else{
				needRead = remain;
			}
			//读取数据
			len = is.read( buff, 0, needRead );
			if( len != -1 ){   
				//写出数据、读多少, 写多少
				outs[index].write( buff, 0, len );
				//强制刷新数据
				outs[index].flush();
				//读多少减多少
				remain = remain - len; 
				//索引指向下一个文件块
				if( remain == 0 ){
					index ++; 
					if( index < size ){
						remain = blocks[index];
					}
				}
			}
		}
		is.close();
		long end = System.currentTimeMillis();
		System.out.println("执行文件切割耗时: "+(end - start)/1000 + " s");
		System.out.println( "程序结束 ..." );
	}
	/**
	 * 文件的合并
	 * @param srcPath 分散文件源文件路径
	 * @param destPath 合并成功后文件的存放路径
	 * @param size 源文件数目
	 * @param speed 合并速度
	 * @param suffix 合并文件后缀
	 * @throws IOException 异常处理
	 */
	public static void fileCombine(String srcPath,String destPath,
	int size,int speed,String suffix) throws IOException{
		long start = System.currentTimeMillis();
		//目标输出流
		OutputStream os = new FileOutputStream(destPath,true);//输出的追加的后边
		//定义创建 4 个输入流的数组.
		InputStream[] is = new InputStream[size];
		for (int i = 0; i < size; i++) {
			is[i] = new FileInputStream(srcPath + i + suffix);
		}
		//获取每个文件大小
		int[] blocks = new int[size];
		for (int i = 0; i < size; i++) {
			blocks[i] = is[i].available();
		}
		int needRead;//一次
		int index = 0;//文件号索引
		int remain = blocks[index];//记录读取到哪个文件
		byte[] buff = new byte[speed];//缓冲,每次读取的大小
		int len = 0;//接收数据
		while (index < size) {
			if( remain > speed ){
				needRead = speed;
			}else{
				needRead = remain;  //剩余数 ...
			}
			//读一次,写一次
			len = is[index].read(buff, 0, needRead);//如果字节够,则将byte数组中的数据读完,否则读剩下的。
			if (len != -1) {//边读取边输出到本地文件中,读多少,输出多少
				os.write(buff, 0, len);//off  需要一个标签来记录,将文件输入到指定文件中。
				//读多少,减多少,直到文件大小被减为0 ,则表明文件被读取完毕,接着判断读取下一个文件
				remain = remain - len;
			}
			if( remain == 0 ){//表明文件被读取完毕,接着判断读取下一个文件
				//记录文件号
				index ++; 
				if( index < size ){
					remain = blocks[index];
				}
			}
		}
		os.close();
		long end = System.currentTimeMillis();
		System.out.println("执行文件合并耗时: "+(end - start)/1000 + " s");
		System.out.println( "程序结束 ..." );
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ljt-tiger

thanks

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值