Java文件的拆分与合并(一)

package cn.com;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.RandomAccessFile;
//文件的拆分和组合
//步骤:
//1 依据源文件大小和每块的大小计算出块数
//2 将每一块写到一个对应的文件
public class FileSeparatorAndUnite {
	long rawFileSize;
	long blocksNumber;
	String rawFileName=null;
	String [] allPaths=null;
	public static void main(String[] args) {
         FileSeparatorAndUnite test=new FileSeparatorAndUnite();
         //拆分文件
         String [] allPaths=test.separatorFile("F:\\2.jpg", 1024*10);
         //组合文件
         test.uniteFile(allPaths, "F:\\99.jpg");
	}
	
	/**
	 * @param rawFilePath   待拆分文件的路径
	 * @param perBlockSize  拆分后每份的大小
	 * @return              各部分路径的数组集合
	 */
	private String[] separatorFile(String rawFilePath,long perBlockSize){
		File rawFile=new File(rawFilePath);
		rawFileName=rawFile.getName();
		rawFileSize=rawFile.length();
		blocksNumber=getBlocksNumber(rawFileSize,perBlockSize);
		allPaths=new String[(int)blocksNumber];
		if (blocksNumber==1) {
			perBlockSize=rawFileSize;
		}
		long perPartSize=0;
		long perPartBeginPosition=0;
		String perPartPath=null;
		for (int i = 1; i <=blocksNumber; i++) {
			if (i<blocksNumber) {
				//每一块的大小就为perBlockSize
				perPartSize=perBlockSize;
			} else {
				//最后一块的大小为总大小-该块的起始位置
                perPartSize=rawFileSize-perPartBeginPosition;
			}
			//得到每一块的path
			if (blocksNumber==1) {
				perPartPath=rawFilePath+".bat";
			} else {
				perPartPath=getPerPartFilePath(rawFilePath, i);
			}
			//操作每一块
			//第一次调用时perPartBeginPosition当然为0
			System.out.println("该Block开始位置:perPartBeginPosition="+perPartBeginPosition);
			writePerPartToFile(rawFilePath, perPartPath, perPartSize, perPartBeginPosition); 
			//计算每一块的在原文件中的起始位置.
			perPartBeginPosition=perPartBeginPosition+perPartSize;
			//保存每一块的路径
			allPaths[i-1]=perPartPath;
			
			System.out.println("该Block大小:perPartSize="+perPartSize);
			
		}
		return allPaths;
		
	}
	
	/**
	 * @param rawFilePath       原文件路径
	 * @param perPartFilePath   每部分对应的路径
	 * @param blockSize         每部分的块大小
	 * @param beginPosition     每部分在原文件中的开始位置 
	 * @return
	 * 
	 * rafForReader.read(buffer, 0, everyTimeReadLen)
	 * 表示:向buffer中读入everyTimeReadLen个字节
	 */
	public boolean writePerPartToFile(String rawFilePath,String perPartFilePath,long blockSize,long beginPosition){
		RandomAccessFile rafForReader=null;
		RandomAccessFile rafForWriter=null;
		boolean isContinueReading=true;
		//每次应该读取的字节数 
		int everyTimeReadLen=0;
		byte [] buffer=new byte[1024*8];
		try {
			rafForReader=new RandomAccessFile(rawFilePath, "r");
			rafForReader.seek(beginPosition);
			File perPartFile=new File(perPartFilePath);
			rafForWriter=new RandomAccessFile(perPartFile, "rw");
			//设置文件大小
			rafForWriter.setLength(blockSize);
			int writerOff=0;
			//设置第一次read()应该读取的字节
			if (blockSize>buffer.length) {
				everyTimeReadLen=buffer.length;
			}else {
				everyTimeReadLen=(int)blockSize;
			}
			while (rafForReader.read(buffer, 0, everyTimeReadLen)!=-1&&isContinueReading){
				  rafForWriter.seek(writerOff);
				  writerOff+=everyTimeReadLen;
				  rafForWriter.write(buffer, 0, everyTimeReadLen);
				  //动态改变下次该读取的字节数
				  if (blockSize-writerOff>buffer.length) {
						everyTimeReadLen=buffer.length;
					}else {
						everyTimeReadLen=(int)blockSize-writerOff;
					}
				  //读取完毕
				  if (everyTimeReadLen==0) {
					isContinueReading=false;
				}
			}
			rafForReader.close();
			rafForWriter.close();
		} catch (Exception e) {
			return false;
		}
		return true;
	}
	
	/**
	 * @param rawFileSize   原文件大小
	 * @param perBlockSize  每块的大小
	 * @return              拆分后块数
	 */
	public long getBlocksNumber(long rawFileSize,long perBlockSize){
		if (rawFileSize<=perBlockSize) {
			return 1;
		} else {
            if (rawFileSize%perBlockSize==0) {
				return (rawFileSize/perBlockSize);
			} else {
                return (rawFileSize/perBlockSize)+1;
			}
		}
	}
	
	/**
	 * @param rawFilePath   原文件路径
	 * @param blockNumer    当前块号码
	 * @return              当前块对应的路径
	 */
	public String getPerPartFilePath(String rawFilePath,int blockNumer){
		String perPartFilePath=rawFilePath+".part"+blockNumer;
		return perPartFilePath;
	}
	
	/**
	 * @param partsPaths      各部分路径
	 * @param unitedFilePath  合并后文件路径
	 */
	public void uniteFile(String [] partsPaths,String unitedFilePath){
		try {
			File perPartFile=null;
			File unitedFile=new File(unitedFilePath);
			FileOutputStream fos=new FileOutputStream(unitedFile);
			FileInputStream fis=null;
			for (int i = 0; i < partsPaths.length; i++) {
				perPartFile=new File(partsPaths[i]);
				fis=new FileInputStream(perPartFile);
				byte [] buffer=new byte[1024*8];
				int len=0;
				while ((len=fis.read(buffer))!=-1) {
					fos.write(buffer, 0, len);
				}
			}
			fis.close();
			fos.close();
		} catch (Exception e) {
		}
	}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

谷哥的小弟

你的鼓励将是我创作的最大动力

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

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

打赏作者

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

抵扣说明:

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

余额充值