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

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

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

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

你可能感兴趣的:(jdk,编程,J#,sun)