package IO流_167_文件分割与合并_文件合并;
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.Enumeration;
import java.util.List;
import java.util.Vector;
/**
-
SequenceInputStream 类 ;
-
SequenceInputStream 表示其他输入流的逻辑串联。它从输入流的有序集合开始,并从第一个输入流开始读取,
-
直到到达文件末尾,接着从第二个输入流读取,依次类推,直到到达包含的最后一个输入流的文件末尾为止。
即先把很多流先组成一个流加在中间,然后在写出去
-
面向对象编程;
*/
public class SplitFile2 {
private String filePath;//文件路径
private int size;//块数
private long blockSize;//每块大小
private List blockPath;//每块存储的名称
private String fileName;//每块名称
private long length;//文件大小private String destBlockPath;//分割后的存放目录
//构造器
public SplitFile2() {
blockPath = new ArrayList();
}
public SplitFile2(String filePath,String destBlockPath) {//构造器相互调用
//this(filePath,1024,destBlockPath);//调用SplitFile(String filePath, long blockSize)
//其他文件名的分割与合并; 调整下位置
this(filePath,destBlockPath,1024);
}
/public SplitFile(String filePath, long blockSize,String destBlockPath) {
this(); //调用 SplitFile()
this.filePath = filePath;
this.blockSize = blockSize;
this.destBlockPath = destBlockPath;
init();//调用
}/
//其他文件名的分割与合并; 调整下位置
public SplitFile2(String filePath,String destBlockPath, long blockSize) {
this(); //调用 SplitFile()
this.filePath = filePath;
this.blockSize = blockSize;
this.destBlockPath = destBlockPath;
init();//调用
}//初始化操作 ;计算块数及确定文件名
public void init(){
File src = null;
//程序的健壮性;判断文件是否为空或者是否存在
if(null==filePath||!((src=new File(filePath)).exists())){
return;
}
if(src.isDirectory()){//判断是否为文件夹
return;
}
//计算块数;判断实际大小与每块大小
this.fileName = src.getName();
this.length= src .length();
//修正每块的大小
if(this.blockSize>length){//如果this.blockSize大小>实际的大小;则改成实际大小
this.blockSize=length;
}
//确定块数;相同整数相除有可能变为0;所有乘1.0;
size = (int) (Math.ceil(length1.0/this.blockSize)); //强转型
initPathName();//确定文件路径
}
//获取每块的名称
private void initPathName(){
for(int i=0;i<size;i++){
this.blockPath.add(destBlockPath+"/"+this.fileName+".part"+i);
}
}
/-
分割后文件存放的目录
-
1.第几块
-
2.起始位置
-
3.实际大小
*/
public void split(){long beginPos = 0;//起始点为0;
long actualBlockSize = blockSize;//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;实际大小
*/
private void splitDetail(int idx,long beginPos,long actualBlockSize){
File src = new File(this.filePath);//创建源
File dest = new File(this.blockPath.get(idx));//目的地
RandomAccessFile raf = null; //输入流
BufferedOutputStream bos = null;//输出流文件的拷贝
try {
raf = new RandomAccessFile(src,“r”);//只读模式’r’
bos = new BufferedOutputStream(new FileOutputStream(dest));
//读取文件
raf.seek(beginPos);//确定起始位置
//缓冲区
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;//结束循环
}
}
//注意这个不能忘 否则分割后的文件内容为空******************
bos.flush();//强制刷出
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally{
CloseUtil.closeIO(bos, raf);
}
}
/**- 文件的合并
- @param destPath
/
/public void merge(String destPath){
// 创建源
File dest = new File(destPath);
//选择流
BufferedOutputStream bos = null;//输出流
try {
bos = new BufferedOutputStream(new FileOutputStream(dest,true));//true是追加;false是覆盖
BufferedInputStream bis = null;//输入流
for(int i=0;i<this.blockPath.size();i++){//blockPath每块存储的名称
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();
CloseUtil.closeIO(bis);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally{
CloseUtil.closeIO(bos);
}
}/
/* - 另一种方法;文件的合并
- @param destPath
/
public void merge2(String destPath){
// 创建源
File dest = new File(destPath);
//选择流 ;BufferedOutputStream缓冲输出流; SequenceInputStream顺序输入流,序列流;
BufferedOutputStream bos = null;//输出流
SequenceInputStream sis = null;//输入流
//创建一个容器;Vector类, 可以实现可增长的对象数组
Vector vi = new Vector();
try {
for(int i=0;i<this.blockPath.size();i++){//blockPath每块存储的名称
vi.add(new BufferedInputStream(new FileInputStream( new File(this.blockPath.get(i)))));
}
bos = new BufferedOutputStream(new FileOutputStream(dest,true));//true是追加;false是覆盖
//elements元素
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();
} catch (Exception e) {
}finally{
CloseUtil.closeIO(sis);
CloseUtil.closeIO(bos);
}
}
/* - SequenceInputStrea序列输入流;Enumeration枚举;elements元素
- @param elements
- @return
*/
private SequenceInputStream SequenceInputStream(Enumeration elements) {
return null;
}
public static void main(String[] args) {
//SplitFile file = new SplitFile(“E:/xp/2020/test/char.java”,50,“E:/xp/2020”);
//其他文件名的分割与合并
SplitFile2 file = new SplitFile2(“E:/xp/2020/学员设置(2020).xls”,“E:/xp/2020”,51);
//System.out.println(file.size);//file.split("E:/xp/2020"); //其他文件名的分割与合并;先分割后合并 file.split(); file.merge2("E:/xp/2020/test1.xls");
}
}
//-------------------------------------------------
package IO流_167_文件分割与合并_文件合并; -
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.RandomAccessFile;
import java.io.SequenceInputStream;
public class CloseUtil {
public static void closeIO(BufferedOutputStream bos, RandomAccessFile raf) {
// TODO Auto-generated method stub
}
public static void closeIO(BufferedInputStream bis) {
// TODO Auto-generated method stub
}
public static void closeIO(BufferedOutputStream bos) {
// TODO Auto-generated method stub
}
public static void closeIO(SequenceInputStream sis) {
// TODO Auto-generated method stub
}
}
//结果-------------------------------------------------