用MappedByteBuffer进行特大文件拷贝分割

目的:
有时候用U盘转移大文件时,U盘空间太小,想写一个小程序能把文件分割方便转移。

问题一:用Buffer直接将文件(1G以上)映入内存,不可能直接进物理内存。
解决方案:将文件用Map映射到一个MappedByteBuffer中

问题二:报告“java.io.IOException: 存储空间不足,无法处理此命令。”异常。
解决方案:将文件分段映射。注意文件较大时必须显式调用
System.gc();
System.runFinalization();
否则还是可能报上述异常。
原因:《JAVA编程思想》4.3 清除:收尾和垃圾收集 有如下说明:
当然,Java可用垃圾收集器回收由不再使用的对象占据的内存。现在考虑
一种非常特殊且不多见的情况。假定我们的对象分配了一个“特殊”内存区
域,没有使用new。[color=red]垃圾收集器只知道释放那些由new分配的内存[/color],所以不知
道如何释放对象的“特殊”内存。为解决这个问题,Java提供了一个名为
finalize()的方法,可为我们的类定义它。

问题三:原文件不可被删除(在程序退出之前)。
解决方案:JDK API 1.60中有“映射的字节缓冲区和它所表示的文件映射关系在该缓冲
区本身成为垃圾回收缓冲区之前一直保持有效。 ”关于此问题众说纷纭,并
且在sun.bug中也在讨论。笔者认为只要最后把映射指向一个无关的文件即可
解决。

关键代码:
frame.jTextField6.getText() //待分割的文件
frame.jTextField5.getText()+"\\"+this.findname() //保存位置
findex //方便以后组合

try{
File fcut = new File(frame.jTextField6.getText());
File fsave = new File(frame.jTextField5.getText()+"\\"+this.findname());
if(!fsave.exists()){
fsave.mkdir();
}
File findex = new File(frame.jTextField5.getText()+"\\"+this.findname()+"\\cut.index");
FileWriter fw = new FileWriter(findex);
BufferedWriter bw = new BufferedWriter(fw);
bw.write(this.findname()+"."+this.findkuozhan(),0,(this.findname()+"."+this.findkuozhan()).length());
bw.newLine();

int num = size_i; //分割份数
long totalsize = fcut.length(); //文件总大小
long persize = totalsize/num; //每个大小

FileInputStream fis = new FileInputStream(fcut);
FileChannel fic = fis.getChannel();

if(persize>buffersize){
for(int i=0;i<num;i++){
RandomAccessFile ras = new RandomAccessFile(frame.jTextField5.getText()+"\\"+this.findname()+"\\"+this.findname()+".cut"+(i+1),"rw");
FileChannel frs = ras.getChannel();
if(i<num-1){
for (int j = 0; j < persize / buffersize; j++) {
if (j < persize / buffersize - 1) {
MappedByteBuffer mibb = fic.map(FileChannel.MapMode.READ_ONLY,i * persize + j * buffersize,buffersize);
MappedByteBuffer mobb = frs.map(FileChannel.MapMode.READ_WRITE,j*buffersize,buffersize);
mobb.put(mibb);
mibb.clear();
mobb.clear();
}else{
MappedByteBuffer mibb = fic.map(FileChannel.MapMode.READ_ONLY,i * persize + j * buffersize,buffersize+persize%buffersize);
MappedByteBuffer mobb = frs.map(FileChannel.MapMode.READ_WRITE,j*buffersize,buffersize+persize%buffersize);
mobb.put(mibb);
mibb.clear();
mobb.clear();
}
}
System.gc();
System.runFinalization();
bw.write(frame.jTextField5.getText()+"\\"+this.findname()+"\\"+this.findname()+".cut"+(i+1),0,(frame.jTextField5.getText()+"\\"+this.findname()+"\\"+this.findname()+".cut"+(i+1)).length());
bw.newLine();
}else{
for (int j = 0; j < persize / buffersize; j++) {
if (j < persize / buffersize - 1) {
MappedByteBuffer mibb = fic.map(FileChannel.MapMode.READ_ONLY,i * persize + j * buffersize,buffersize);
MappedByteBuffer mobb = frs.map(FileChannel.MapMode.READ_WRITE,j*buffersize,buffersize);
mobb.put(mibb);
mibb.clear();
mobb.clear();
}else{
MappedByteBuffer mibb = fic.map(FileChannel.MapMode.READ_ONLY,i * persize + j * buffersize,totalsize-(i * persize + j * buffersize));
MappedByteBuffer mobb = frs.map(FileChannel.MapMode.READ_WRITE,j*buffersize,totalsize-(i * persize + j * buffersize));
mobb.put(mibb);
mibb.clear();
mobb.clear();
}
}
System.gc();
System.runFinalization();
bw.write(frame.jTextField5.getText()+"\\"+this.findname()+"\\"+this.findname()+".cut"+(i+1),0,(frame.jTextField5.getText()+"\\"+this.findname()+"\\"+this.findname()+".cut"+(i+1)).length());
bw.close();
fw.close();
}
ras.close();
frs.close();
}
fis.close();
fic.close();

}else{
for(int i=0;i<num;i++){
RandomAccessFile ras = new RandomAccessFile(frame.jTextField5.getText()+"\\"+this.findname()+"\\"+this.findname()+".cut"+(i+1),"rw");
FileChannel frs = ras.getChannel();
if(i<num-1){

MappedByteBuffer mibb = fic.map(FileChannel.MapMode.READ_ONLY,i * persize,persize);
MappedByteBuffer mobb = frs.map(FileChannel.MapMode.READ_WRITE,0,persize);
mobb.put(mibb);
mibb.clear();
mobb.clear();

System.gc();
System.runFinalization();
bw.write(frame.jTextField5.getText()+"\\"+this.findname()+"\\"+this.findname()+".cut"+(i+1),0,(frame.jTextField5.getText()+"\\"+this.findname()+"\\"+this.findname()+".cut"+(i+1)).length());
bw.newLine();
}else{

MappedByteBuffer mibb = fic.map(FileChannel.MapMode.READ_ONLY,i * persize,totalsize-i * persize);
MappedByteBuffer mobb = frs.map(FileChannel.MapMode.READ_WRITE,0,totalsize-i * persize);
mobb.put(mibb);
mibb.clear();
mobb.clear();

System.gc();
System.runFinalization();
bw.write(frame.jTextField5.getText()+"\\"+this.findname()+"\\"+this.findname()+".cut"+(i+1),0,(frame.jTextField5.getText()+"\\"+this.findname()+"\\"+this.findname()+".cut"+(i+1)).length());
bw.close();
fw.close();
}
ras.close();
frs.close();
}
fis.close();
fic.close();


}
jop = new JOptionPane();
jop.showMessageDialog(frame.getContentPane(),"文件分割完毕!", "成功", JOptionPane.ERROR_MESSAGE);
}catch(Exception e){
jop = new JOptionPane();
jop.showMessageDialog(frame.getContentPane(),e.toString(), "错误", JOptionPane.ERROR_MESSAGE);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值