IO流之切割合并文件

java1234

共 4995字,需浏览 10分钟

 ·

2020-08-19 06:30

点击上方蓝色字体,选择“标星公众号”

优质文章,第一时间送达

66套java从入门到精通实战课程分享

切割文件,思路就是 以每块多大的分量去切割成多少块,

比方说 1024 的 文件以 500 切,就得切成 3块,那么就是  500,500 24 的三块

也就是说最后一块可能装不满 500,那就得取实际数量了,也就是 24

所以就可以把文件分成 3 份,各份得起始点就是  

            第一块:0,500

            第二块:500,1000

            第三块:1000,1024

然后进行读写,读得时候可以使用 RandomAccessFile 的  seek 方法设置开始读取的地方,然后结束的地方再使用 输入的 结束点进行判断,从而进行分割

说的可能有点不好懂,结合代码来看吧

类的私有属性放这几个:

// 文件路径
  private String filePath;
  
  // 文件大小
  private long fileLength;
  
  // 文件名称
  private String fileName;
  
  // 以多大来切割文件
  private long blockSize;
  
  // 文件块数
  private int size;
  
  // 切割后的文件的存放路径
  private String destPath;
  
  // 切割后的每块的文件名
  private List<String> destFileName;


初始化方法,初始化的时候,确定切几块,一块多大,已经切成块后的文件名,等等:

public SplitFileDemo() {
    super();
    this.destFileName = new ArrayList();
  }
  
  public SplitFileDemo(String filePath,String destPath) {
    this(filePath, 1024*1024, destPath);
  }
  
  public SplitFileDemo(String filePath,long blockSize,String destPath) {
    this();
    this.filePath = filePath;
    this.blockSize = blockSize;
    this.destPath = destPath;
    init();
  }
  
  /**
   *
   * @Title: init
   * @Description: 初始化必须参数,比如说文件切割后的名字,分成几块,之类的
   * @param:
   * @return: void
   * @throws
   */

  public void init() {
    File src = null;
    // 如果 文件地址为空,或者文件不存在则终止程序
    if(this.filePath == null || !(src = new File(this.filePath)).exists()) {
      return ;
    }
    // 该地址为文件夹也终止
    if(src.isDirectory()) {
      return ;
    }
    
    File dest = null;
    // 如果目标文件不存在则终止程序
    if( this.destPath == null  ) {
      return ;
    }
    dest = new File(this.destPath);
    // 如果目标文件不存在则创建
    if(!dest.exists()) {
      dest.mkdirs();
    }
    
    // 文件大小
    this.fileLength = src.length();
    
    // 文件名称
    this.fileName = src.getName();
    
    if(this.blockSize > this.fileLength) {
      this.blockSize = this.fileLength;
    }
    
    // 分块
    this.size = (int)Math.ceil( (src.length()*1.0 / this.blockSize) );
    
    initDestFileName();
  }
  
  /**
   *
   * @Title: initDestFileName
   * @Description: 初始化切割后的文件的名称
   * @param:
   * @return: void
   * @throws
   */

  public void initDestFileName() {
    for (int i = 0; i < this.size; i++) {
      this.destFileName.add( this.destPath + File.separator + this.fileName + ".temp"+i );
    }
  }


然后就是文件切割,确定文件的起始点:

/**
   *
   * @Title: split
   * @Description: 切割文件 ,确定起始点
   * @param:
   * @return: void
   * @throws
   */

  public void split() {
    long beginPos = 0;
    long actualBlockSize = this.blockSize;
    
    for (int i = 0; i < this.size; i++) {
      // 当最后一块的大小比分块的大小小的时候,实际大小为 总长度-起点
      if(this.fileLength - beginPos <= this.blockSize ) {
        actualBlockSize = this.fileLength - beginPos;
      }
      
      splitDetil(i, beginPos, actualBlockSize);
      // 起点 = 上一次的结尾 + 实际读取的长度
      beginPos += actualBlockSize;
    }
  }

最后就是文件切割的详细方法,如何切割:

/**
   *
   * @Title: splitDetil
   * @Description: 切割文件的具体实现方法
   * @param:
   * @return: void
   * @throws
   */

  public void splitDetil(int index,long beginPos,long actualBlockSize) {
    // 创建源文件
    File src = new File(this.filePath);
    File desc = new File(this.destFileName.get(index));
    
    RandomAccessFile raf = null;
    BufferedOutputStream bos = null;
    try {
      // 设置只读读取
      raf = new RandomAccessFile(src, "r");
      bos = new BufferedOutputStream( new FileOutputStream(desc) );
      
      // 读取文件
      raf.seek(beginPos);
      
      // 缓冲
      byte [] flush = new byte[1024];
      // 记录每次读取的长度
      int len = 0;
      while (-1 != (len = raf.read(flush))) {
        if( (actualBlockSize - len )>0 ) {
          bos.write(flush, 0, len);
          actualBlockSize -= len;
        }else {
          // 写出最后一块后关闭循环
          bos.write(flush,0,(int)actualBlockSize);
          break;
        }
      }
      
      bos.flush();
      
    } catch (FileNotFoundException e) {
      e.printStackTrace();
    } catch (IOException e) {
      e.printStackTrace();
    } finally {
      try {
        bos.close();
      } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
      }
      try {
        raf.close();
      } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
      }
    }
    
  }


最后就是文件合并了,文件合并就简单多了,因为 初始化文件的时候就确定了切块后的每块的文件名,只需要将其全部读取出来然后写出就ok,记得这里的 new FileOutputStream( file, true ) 构造方法应该这样写,因为是合并文件,所以这里得 是追加

代码如下:

/**
   * 文件合并
   * @Title: merge
   * @Description: TODO(这里用一句话描述这个方法的作用)
   * @param: @param 合并后的文件位置
   * @return: void
   * @throws
   */

  public void merge(String destPath) {
    File dest = new File(destPath);
    if(destPath==null) {
      return ;
    }
    // 目标文件不存在则创建
    if(!new File(dest.getParent()).exists()) {
      new File(dest.getParent()).mkdirs();
    }
    
    BufferedOutputStream bos = null;
    BufferedInputStream bis = null;
    try {
      // 此处是追加,因为是文件合并
      bos = new BufferedOutputStream( new FileOutputStream( dest ,true) );
      for (int i = 0; i < this.size; i++) {
        
        bis = new BufferedInputStream( new FileInputStream( new File(this.destFileName.get(i)) ) );
        
        byte [] flush = new byte[1024];
        int len = 0;
        while( -1!=(len = bis.read(flush)) ) {
          bos.write(flush,0,len);
        }
        
        bos.flush();
        bis.close();
      }
    } catch (Exception e) {
      e.printStackTrace();
    } finally {
      try {
        bos.close();
      } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
      }
    }
    
  }


运行示例:

public static void main(String[] args) {
    SplitFileDemo splitFileDemo = new SplitFileDemo("F:\\msb\\刘明湘 - 漂洋过海来看你.mp3", 1024*1024, "F:/lmx");
    
    //splitFileDemo.split();
    splitFileDemo.merge("F:/msb/lxm.mp3");
  }

自己动手试试吧,多想想


版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。

本文链接:

https://blog.csdn.net/yali_aini/article/details/81942036




     




感谢点赞支持下哈 

浏览 35
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报