来源:http://www.bjsxt.com/
一、S02E164_01IO_文件分割与合并_RandomAccessFile
package com.test.io.file.split0merge;
import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
/**
* 文件分割的思路
* 第一步:分割的准备
* 1、分割的块数 size n块
* 2、确定每一块的大小 blockSize
* 最后一块的大小:总的文件大小-(n-1)*blockSize
* 3、每块的名称
* 第二步
* 4、分割
* a)第几块、每块的起点、实际大小
* b)文件分割
*/
public class TestRandomAccessFile {
public static void main(String[] args) throws IOException {
RandomAccessFile raf = new RandomAccessFile(new File("G:/java/test/path.java"), "r");
raf.seek(20);
//定义缓冲大小
byte[] flush = new byte[1024];
//接收长度
int len = 0;
while(-1 != (len=raf.read(flush))){
if(len >=200){
System.out.println(new String(flush,0,200));
break;
}else{
System.out.println(new String(flush,0,len));
}
}
raf.close();
}
}
二、S02E165_01IO_文件分割与合并_初始化各项参数
三、S02E166_01IO_文件分割与合并_分割
四、S02E167_01IO_文件分割与合并_文件合并_SequenceInputStream
package com.test.io.file.split0merge;
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;
public class SplitFile {
//文件路径
private String filePath;
//文件名
private String fileName;
//文件大小
private long length;
//块数
private int size;
//每块的大小
private long blockSize;
//分割后的存放目录
private String desBlockPath;
//每块的名称
private List<String> blockPath;
public SplitFile(){
blockPath = new ArrayList<String>();
}
public SplitFile(String filePath,String desBlockPath){
this(filePath,desBlockPath,1024);
}
public SplitFile(String filePath,String desBlockPath,long blockSize){
this();
this.filePath = filePath;
this.desBlockPath = desBlockPath;
this.blockSize = blockSize;
init();
}
/**
* 初始化操作 计算块数、确定文件名
*/
public void init(){
File src = null;
//健壮性
if( (null==filePath) || !((src=new File(filePath)).exists()) ){
return;
}
if(src.isDirectory()){
return;
}
//文件名
fileName = src.getName();
//计算块数 实际总大小与每块大小
length = src.length();
//修正 每块大小超过实际总大小
if(blockSize > length){
blockSize = length;
}
//确定块数
size = (int)Math.ceil(length*1.0/blockSize);//两整数,被除数比除数小,结果为0/解决:类型升级
//确定每块的文件路径
initPathName();
}
private void initPathName(){
for (int i = 0; i < size; i++) {
blockPath.add(desBlockPath + "/" + fileName + ".part" + i);
}
}
/**
* 文件的分割
* 1、第几块
* 2、起始位置
* 3、实际的大小
* @param desPath 分割文件的存放目录
*/
public void split(){
long beginPos = 0;//起始点
long actualBlockSize = blockSize;//实际每块的大小
//计算所有块的大小、位置、索引
for (int i = 0; i < size; i++) {
if(i == size-1){//最后一块
actualBlockSize = length - beginPos;
}
splitDetail(i,beginPos,actualBlockSize);
beginPos += actualBlockSize;
}
}
/**
* 文件的分割 输入输出
* 文件拷贝
* @param idx 第几块
* @param beginPos 起始点
* @param actualBolckSize 实际块大小
*/
public void splitDetail(int idx,long beginPos,long actualBolckSize){
//1、创建源
File src = new File(filePath);//源文件
File des = new File(blockPath.get(idx));
//2、选择流
RandomAccessFile raf = null;//输入流
BufferedOutputStream bos = null;//输出流
try {
raf = new RandomAccessFile(src,"r");
bos = new BufferedOutputStream(new FileOutputStream(des));
//读取文件
raf.seek(beginPos);
//缓冲区
byte[] flush = new byte[1024];
//接收长度
int len = 0;
while(-1 != (len=raf.read(flush))){//一块可能一次读完,也可能分多次读完
//System.out.println(len);
if(actualBolckSize - len >= 0 ){//查看是否读够
//写出
bos.write(flush, 0, len);
actualBolckSize -= len;//剩余量
}else{//写出最后一次的剩余量
bos.write(flush, 0, (int)actualBolckSize);
break;
}
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally{
try {
bos.close();
raf.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
/**
* 文件的合并
* @param desPath
*/
public void mergeFile(String desPath){
//创建源
File des = new File(desPath);
//选择流
BufferedOutputStream bos = null;
try {
bos = new BufferedOutputStream(new FileOutputStream(des,true));//追加
BufferedInputStream bis = null;
for (int i = 0; i < blockPath.size(); i++) {
bis = new BufferedInputStream(new FileInputStream(new File(blockPath.get(i))));
byte[] flush = new byte[1024];
int len = 0;
while(-1 != (len=bis.read(flush))){
bos.write(flush, 0, len);
}
bis.close();
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally{
try {
bos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
/**
* 文件的合并
* SequenceInputStream表示其他输入流的逻辑串联。
* 它从输入流的有序集合开始,并从第一个输入流开始读取,直到到达文件末尾,
* 接着从第二个输入流读取,依次类推,直到到达包含的最后一个输入流的文件末尾为止。
*
* SequenceInputStream(Enumeration<? extends InputStream> e)传入参数为枚举类型
* <br>Enumeration<InputStream> java.util.Vector.elements()返回枚举
* @param desPath
*/
public void mergeFileBySequenceInputStream(String desPath){
//创建源
File des = new File(desPath);
//选择流
BufferedOutputStream bos = null;//输出流
SequenceInputStream sis = null;//输入流
//创建一个容器存放流
Vector<InputStream> vi = new Vector<InputStream>();
try {
bos = new BufferedOutputStream(new FileOutputStream(des));
for (int i = 0; i < blockPath.size(); i++) {
vi.add(new BufferedInputStream(new FileInputStream(new File(blockPath.get(i)))));
}
sis = new SequenceInputStream(vi.elements());//SequenceInputStream(Enumeration<? extends InputStream> e)
byte[] flush = new byte[1024];
int len = 0;
while(-1 != (len=sis.read(flush))){
bos.write(flush, 0, len);
}
sis.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally{
try {
bos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
/*************************************************************/
/**
* @param args
*/
public static void main(String[] args) {
SplitFile split = new SplitFile("G:/java/test/src.txt","G:/java/test",400);
System.out.println(split.size);
split.split();
split.mergeFile("G:/java/test/des.txt");
split.mergeFileBySequenceInputStream("G:/java/test/desBySequenceInputStream.txt");
}
}