IO流之切割合并文件
共 4995字,需浏览 10分钟
·
2020-08-19 06:30
点击上方蓝色字体,选择“标星公众号”
优质文章,第一时间送达
切割文件,思路就是 以每块多大的分量去切割成多少块,
比方说 1024 的 文件以 500 切,就得切成 3块,那么就是 500,500 24 的三块
也就是说最后一块可能装不满 500,那就得取实际数量了,也就是 24
所以就可以把文件分成 3 份,各份得起始点就是
第一块:0,500
第二块:500,1000
第三块:1000,1024
然后进行读写,读得时候可以使用 RandomAccessFile 的 seek 方法设置开始读取的地方,然后结束的地方再使用 输入的 结束点进行判断,从而进行分割
说的可能有点不好懂,结合代码来看吧
类的私有属性放这几个:
// 文件路径
private String filePath;
// 文件大小
private long fileLength;
// 文件名称
private String fileName;
// 以多大来切割文件
private long blockSize;
// 文件块数
private int size;
// 切割后的文件的存放路径
private String destPath;
// 切割后的每块的文件名
private List<String> destFileName;
初始化方法,初始化的时候,确定切几块,一块多大,已经切成块后的文件名,等等:
public SplitFileDemo() {
super();
this.destFileName = new ArrayList();
}
public SplitFileDemo(String filePath,String destPath) {
this(filePath, 1024*1024, destPath);
}
public SplitFileDemo(String filePath,long blockSize,String destPath) {
this();
this.filePath = filePath;
this.blockSize = blockSize;
this.destPath = destPath;
init();
}
/**
*
* @Title: init
* @Description: 初始化必须参数,比如说文件切割后的名字,分成几块,之类的
* @param:
* @return: void
* @throws
*/
public void init() {
File src = null;
// 如果 文件地址为空,或者文件不存在则终止程序
if(this.filePath == null || !(src = new File(this.filePath)).exists()) {
return ;
}
// 该地址为文件夹也终止
if(src.isDirectory()) {
return ;
}
File dest = null;
// 如果目标文件不存在则终止程序
if( this.destPath == null ) {
return ;
}
dest = new File(this.destPath);
// 如果目标文件不存在则创建
if(!dest.exists()) {
dest.mkdirs();
}
// 文件大小
this.fileLength = src.length();
// 文件名称
this.fileName = src.getName();
if(this.blockSize > this.fileLength) {
this.blockSize = this.fileLength;
}
// 分块
this.size = (int)Math.ceil( (src.length()*1.0 / this.blockSize) );
initDestFileName();
}
/**
*
* @Title: initDestFileName
* @Description: 初始化切割后的文件的名称
* @param:
* @return: void
* @throws
*/
public void initDestFileName() {
for (int i = 0; i < this.size; i++) {
this.destFileName.add( this.destPath + File.separator + this.fileName + ".temp"+i );
}
}
然后就是文件切割,确定文件的起始点:
/**
*
* @Title: split
* @Description: 切割文件 ,确定起始点
* @param:
* @return: void
* @throws
*/
public void split() {
long beginPos = 0;
long actualBlockSize = this.blockSize;
for (int i = 0; i < this.size; i++) {
// 当最后一块的大小比分块的大小小的时候,实际大小为 总长度-起点
if(this.fileLength - beginPos <= this.blockSize ) {
actualBlockSize = this.fileLength - beginPos;
}
splitDetil(i, beginPos, actualBlockSize);
// 起点 = 上一次的结尾 + 实际读取的长度
beginPos += actualBlockSize;
}
}
最后就是文件切割的详细方法,如何切割:
/**
*
* @Title: splitDetil
* @Description: 切割文件的具体实现方法
* @param:
* @return: void
* @throws
*/
public void splitDetil(int index,long beginPos,long actualBlockSize) {
// 创建源文件
File src = new File(this.filePath);
File desc = new File(this.destFileName.get(index));
RandomAccessFile raf = null;
BufferedOutputStream bos = null;
try {
// 设置只读读取
raf = new RandomAccessFile(src, "r");
bos = new BufferedOutputStream( new FileOutputStream(desc) );
// 读取文件
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 {
try {
bos.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
raf.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
最后就是文件合并了,文件合并就简单多了,因为 初始化文件的时候就确定了切块后的每块的文件名,只需要将其全部读取出来然后写出就ok,记得这里的 new FileOutputStream( file, true ) 构造方法应该这样写,因为是合并文件,所以这里得 是追加
代码如下:
/**
* 文件合并
* @Title: merge
* @Description: TODO(这里用一句话描述这个方法的作用)
* @param: @param 合并后的文件位置
* @return: void
* @throws
*/
public void merge(String destPath) {
File dest = new File(destPath);
if(destPath==null) {
return ;
}
// 目标文件不存在则创建
if(!new File(dest.getParent()).exists()) {
new File(dest.getParent()).mkdirs();
}
BufferedOutputStream bos = null;
BufferedInputStream bis = null;
try {
// 此处是追加,因为是文件合并
bos = new BufferedOutputStream( new FileOutputStream( dest ,true) );
for (int i = 0; i < this.size; i++) {
bis = new BufferedInputStream( new FileInputStream( new File(this.destFileName.get(i)) ) );
byte [] flush = new byte[1024];
int len = 0;
while( -1!=(len = bis.read(flush)) ) {
bos.write(flush,0,len);
}
bos.flush();
bis.close();
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
bos.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
运行示例:
public static void main(String[] args) {
SplitFileDemo splitFileDemo = new SplitFileDemo("F:\\msb\\刘明湘 - 漂洋过海来看你.mp3", 1024*1024, "F:/lmx");
//splitFileDemo.split();
splitFileDemo.merge("F:/msb/lxm.mp3");
}
自己动手试试吧,多想想
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:
https://blog.csdn.net/yali_aini/article/details/81942036
感谢点赞支持下哈