RandomAccessFile分割、还原文件(一)
RandomAccessFileadmin 发布于:2015-12-10 17:45:50
阅读:loading
想写个例子去分割大文件已经很久了,由于一些问题始终没有搞明白,故一直没去做,然而今天还是艰难的下手了,实现了这个功能示例,并且稍微完善了一下,基于RandomAccessFile随机读取文件,分割、还原文件等动作。本篇文章主要关注一下一个简单版本的分割文件、合并文件的核心模块处理逻辑,目的在于像我一样渣渣水平的人可以从基础入门,对于一些运算逻辑太复杂,或者是封装的太深的代码不太容易对于这块儿的新手儿来理解,所以本篇我重点在于精简代码,并给出相关的注释,在异常的处理上就放宽松点吧,文件的分割网上示例非常多,我理解的文件分割与我们数据库的数据分页原理类似,都是获取到总记录数total,再根据每页显示数据条数pageSize,先得出一共有多少页totalPage,再从1开始循环至totalPage,将每页的数据读取出来,而文件分割是一样的,只不过是将每页的字节单独存储为一个文件,参考代码如下:
1.文件分割
package com;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.RandomAccessFile;
/**
* 按指定文件大小分割文件
* @author chendd
*/
public class SplitFileCore {
private long blockLength;// 分割单个文件大小
private long currentTotal;// 当前分割次数的位置
public SplitFileCore(int blockLength) {
this.blockLength = blockLength;
}
public void split(File srcFile, String splitFolder) throws Exception {
long fileLens = srcFile.length();// 文件大小
if (fileLens <= this.blockLength) {
System.out.println("分割的文件大小 " + this.blockLength + " 大于文件的大小!");
return;
}
RandomAccessFile raf = new RandomAccessFile(srcFile, "r");
// 根据分割块大小,计算一共有多少块文件
int blockCount = (int) (fileLens % this.blockLength);
if (blockCount == 0) {
blockCount = (int) (fileLens / this.blockLength);
} else {
blockCount = (int) (fileLens / this.blockLength) + 1;
}
// 按快进行读取文件
String srcFileName = srcFile.getName();
for (int i = 0; i < blockCount; i++) {
File destFile = new File(splitFolder + File.separator + srcFileName
+ "." + (i + 1) + ".part");
splitFileDetail(destFile, raf);// 分割文件
}
if (raf != null) {
raf.close();
}
}
private void splitFileDetail(File destFile, RandomAccessFile raf)
throws IOException {
byte b[] = new byte[1024];
int lens = 0;
// 如果文件目录不存在,则创建
if (destFile.getParentFile().exists() == false) {
destFile.getParentFile().mkdirs();
}
raf.seek(currentTotal);// 设置开始读取的位置
long currentMax = raf.getFilePointer() + this.blockLength;
BufferedOutputStream bos = new BufferedOutputStream(
new FileOutputStream(destFile));
while ((lens = raf.read(b)) != -1) {
// 判断文件读取的大小,避免已经读取超过每块的大小了
if (currentTotal + lens > currentMax) {
break;
}
bos.write(b, 0, lens);
currentTotal += lens;// 累加读取的文件数据
}
if (bos != null) {
bos.flush();
bos.close();
}
}
public static void main(String[] args) throws Exception {
File srcFile = new File("d:\\splitFolder\\中国政区2500.jpg");
String splitFolder = "d:\\splitFolder";// 分割存储路径
SplitFileCore splitFile = new SplitFileCore(1024 * 1024);// 按1M的大小去分割文件
splitFile.split(srcFile, splitFolder);
System.out.println("文件分割完毕...");
}
}
2.文件合并
package com;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
/**
* 合并文件
* @author chendd
*/
public class MergeFileCore {
public static void main(String[] args) throws IOException,
ClassNotFoundException {
String propFile = "d:\\splitFolder";
File file = new File(propFile);
File files[] = file.listFiles();
BufferedOutputStream bos = new BufferedOutputStream(
new FileOutputStream(propFile + File.separator + "还原文件.jpg",
true));
byte b[] = new byte[1024];
// 循环读取文件
for (File f : files) {
if (f.getName().endsWith(".part") == false) {
continue;
}
InputStream is = new FileInputStream(f);
int lens = 0;
while ((lens = is.read(b)) != -1) {
bos.write(b, 0, lens);
}
is.close();
}
bos.flush();
bos.close();
System.out.println("文件还原完毕");
}
}
至此,分割一个二进制的文件是没有问题的,至于前文中所说的没想明白的问题,其实是分割字符文件时,按由于是按字节进行分割,如果遇到中文字符会出现字符被截取的不完整,乱码的问题,这个问题后来参考了一些意见:
1)分割文件不等于时文件分段读取;
2)有乱码不要紧,再合并文件时就正常了;
3)或许按行读取文件的方式可以一试。
点赞