使用 RandomAccessFile 随机访问文件类以及面向对象封装的思想
完成对指定文件的分割
public class SplitFile {
private File f;//待分割的文件
private int blocksize;//指定分割大小
private String destname;//分割后放置的文件夹名称
private int size;//文件分割块数
private long len;//文件总长度
public SplitFile(String fname, int blocksize, String destname) {//构造函数
this.f = new File(fname);//传入需要操作的文件名
this.blocksize = blocksize;//文件分割大小
this.destname=destname;//分割后文件存储位置
init();//初始化
}
public SplitFile(String fname, String destname) {//重载构造函数,默认分割大小为1024字节
this(fname,1024,destname);
}
private void init() {
len = this.f.length();//得到文件长度
size = (int) (Math.ceil(len * 1.0 / blocksize));//得到分割后每块文件大小
}
public void split() throws IOException {//分割函数
int beginpos = 0;//起始位置
int actualsize = 0;//实际读取长度
for (int i = 0; i < size; i++) {
beginpos = i * blocksize;//起始位置最开始为0,然后是分割大小的倍数。
if (i == size - 1) {//如果是最后一块,考虑无法平均分割
actualsize = (int) len % blocksize;//最后一次要获取的实际长度
} else {
actualsize = blocksize;//不是最后一次 每次读取指定长度
}
System.out.println(i + "-----" + beginpos + "--------" + actualsize);
//打印第几块,该块起始位置,该块实际大小
spiltdetail(beginpos, actualsize,i);//循环调用实际分割函数
}
}
private void spiltdetail(int beginpos, int actualsize, int i) throws IOException {
//实际分割函数,根据上面的函数计算得到的每块大小进行读取和写入
RandomAccessFile raf = new RandomAccessFile(this.f, "r");//随机访问文件类:读取模式
File ff=new File(destname);
ff.mkdir();
RandomAccessFile raf2=new RandomAccessFile(new File(destname+"/"+i+"copy.txt"),"rw");//读入新的文件内
raf.seek(beginpos);//设定起始位置
byte[] flush = new byte[1024];
int flag;
while ((flag = raf.read(flush)) != -1) {
if (actualsize > flag) {//如果需要读取的长度大于本次缓冲数组读取的长度,则全部读取
raf2.write(flush, 0, flush.length);
// System.out.println(new String(flush, 0, flush.length));
actualsize = actualsize - flag;
} else {//否则读取所需要的部分
raf2.write(flush, 0, actualsize);
// System.out.println(new String(flush, 0, actualsize));
break;
}
}
raf2.close();
raf.close();//关闭流,后开先关
}
public static void main(String[] args) throws IOException {
SplitFile sf=new SplitFile("sc.jpg",1024,"dest");//测试用例,分别指定待分割文件名,分割大小,分割后文件放置的目录
sf.split();
System.out.println("split over");
}
}
可以添加一个方法实现分割文件的合并:
public void merge(String dest2) throws IOException {
OutputStream os=new BufferedOutputStream(new FileOutputStream(dest2,true));//一个输出流,append为true代表续写模式
for(int i=0;i<size;i++){//创建多个输入流的个数与文件分割次数一致
InputStream is=new BufferedInputStream(new FileInputStream(destname+"/"+i+"copy.txt"));
byte[]flush=new byte[1024];//缓冲容器
int flag;
while((flag=is.read(flush))!=-1){
os.write(flush,0,flag);
}
os.flush();
is.close();
}
os.close();
}
当多个输入流进行操作的时候考虑使用序列流方法
步骤:创建vector容器,将多个输入流放入容器中,将容器传入序列流中
public void merge(String dest2) throws IOException {
OutputStream os=new BufferedOutputStream(new FileOutputStream(dest2,true));
Vector<InputStream> vi=new Vector<>();
SequenceInputStream sis=null;//序列流,可以装多个流
for(int i=0;i<size;i++){//建立输入流的个数与文件分割次数一致
vi.add(new BufferedInputStream(new FileInputStream(destname+"/"+i+"copy.txt")));
}
sis=new SequenceInputStream(vi.elements());//Vector容器的elements功能是返回容器内组件的枚举
byte[]flush=new byte[1024];//缓冲容器
int flag;
while((flag=sis.read(flush))!=-1){
os.write(flush,0,flag);
}
os.close();
}