文件分割:下载工具就是用这个原理来下载的;比如一部电影,有5个人同时在下,那么就把
* 这个电影分割成5部分,每人下一部分然后再合起来,这就是为什么下载这么快。
* 但是必需先对这个文件进行分割。
* randomAccessFile:随机访问:支持读取和写入随机访问文件
* sequenceInputStream:序列流,用于文件的合并
分割文件
//分割文件后,放到其他文件里
public static void test1(int i,int begin,int actualSize) throws IOException{
RandomAccessFile rf = new RandomAccessFile(
new File("src/SOA.txt"),"r");//参数r是读取
RandomAccessFile rf2 = new RandomAccessFile(
new File("src/dest/"+i+"SOA.txt"),"rw");//参数rw是写入
rf.seek(begin);//设置文件指针偏移,从该文件的开头测量,发生下一次读取或写入
byte[] datas = new byte[1024];
int len = -1;
while((len = rf.read(datas))!=-1){
if(actualSize>len){//获取本次读取的所有内容
rf2.write(datas,0,len);
actualSize -=len;
}else{
rf2.write(datas,0,actualSize);
break;
}
}
rf2.close();
rf.close();
}
如何分块的方法
//分块
public static void test() throws IOException {
File file = new File("src/SOA.txt");
//总长度
long len = file.length();
//每块大小
int blockSize = 1024;
//多少块 ceil向上取整
int size = (int)Math.ceil(len*1.0/blockSize);
int begin = 0;//起始位置
int actualSize = (int)(blockSize>len?len:blockSize);//实际大小
for (int i = 0; i < size; i++) {
begin =blockSize*i;
if(i==size-1){//最后一块的时候
actualSize = (int)len;
}else{
actualSize =blockSize;
len -=actualSize;
}
System.out.println(i+"---"+begin+"----"+actualSize);
test1(i,begin,actualSize);
}
}
面向对象思想 封装分割方法
//源头
private File src;
//目的地
private String destDir;
//所以分割后的文件路径
private List<String> destPaths;
//每块大小
private int blockSize;
//块数
private int size;
public TestFileSplit(String src, String destDir, int blockSize) {
this.src = new File(src);
this.destDir = destDir;
this.blockSize = blockSize;
this.destPaths = new ArrayList<String>();
init();
}
//初始化
private void init(){
//总长度
long len = this.src.length();
//每块大小
int blockSize = 1024;
//多少块 ceil向上取整
this.size = (int)Math.ceil(len*1.0/blockSize);
//路劲
for (int i = 0; i < size; i++) {
this.destPaths.add(this.destDir+"/"+i+"-"+this.src.getName());
}
}
private void test1(int i,int begin,int actualSize) throws IOException{
RandomAccessFile rf = new RandomAccessFile(this.src,"r");//参数r是读取
RandomAccessFile rf2 = new RandomAccessFile(this.destPaths.get(i),"rw");//参数rw是写
入
rf.seek(begin);//设置文件指针偏移,从该文件的开头测量,发生下一次读取或写入
byte[] datas = new byte[1024];
int len = -1;
while((len = rf.read(datas))!=-1){
if(actualSize>len){//获取本次读取的所有内容
rf2.write(datas,0,len);
actualSize -=len;
}else{
rf2.write(datas,0,actualSize);
break;
}
}
rf2.close();
rf.close();
}
public void test() throws IOException {
//总长度
long len = src.length();
int begin = 0;//起始位置
int actualSize = (int)(blockSize>len?len:blockSize);//实际大小
for (int i = 0; i < size; i++) {
begin =blockSize*i;
if(i==size-1){//最后一块的时候
actualSize = (int)len;
}else{
actualSize =blockSize;
len -=actualSize;
}
test1(i,begin,actualSize);
}
}
调用:
TestFileSplit tfs = new TestFileSplit("src/SOA.txt", "src/dest", 1024*2);
tfs.test();
合并文件
//合并文件
public void merge(String destPath) throws IOException {
OutputStream os = new BufferedOutputStream(new FileOutputStream(destPath,true));
for (int i= 0; i< destPaths.size(); i++) {
InputStream is = new BufferedInputStream(new FileInputStream(destPaths.get(i)));
//拷贝
byte[] flush = new byte[6];//缓冲容器
int len = -1;//接收长度
while ((len = is.read(flush))!=-1){
os.write(flush,0,len);
}
os.flush();
is.close();
}
os.close();
}
调用
TestFileSplit tfs = new TestFileSplit("src/SOA.txt", "src/dest", 1024);
tfs.test();
tfs.merge("copy-SOA.txt");
用序列流来合并
public void merge2(String destPath) throws IOException {
OutputStream os = new BufferedOutputStream(new FileOutputStream(destPath,true));
Vector<InputStream> vi = new Vector<InputStream>();
SequenceInputStream sis = null;
for (int i= 0; i< destPaths.size(); i++) {
vi.add(new BufferedInputStream(new FileInputStream(destPaths.get(i))));
//拷贝
}
sis = new SequenceInputStream(vi.elements());
byte[] flush = new byte[6];//缓冲容器
int len = -1;//接收长度
while ((len = sis.read(flush))!=-1){
os.write(flush,0,len);
}
os.flush();
sis.close();
os.close();
}