菜鸟笔记
提升您的技术认知

断点续传实现

断点续传实现:

简单来说应该分为两个角度来看待:

1、将要续传的文件

2、续传的文件

一、将要续传的文件

先说说将要续传的文件,既然是续传,那么肯定要有个标识,举例说明一下:

    事先准备一个文件,大小是1852字节,第一次读取该文件的io流(0-1024字节),并将1024作为下次读取的首值,存储1024这个变量,就是在这个过程中的标识(记录所读到的位置) ,通过这个标识,我们下次读取的字节范围应该就是(1024-1852)字节。

   要完成这个需求,应该考虑二个角度,

   1)、这个标识放在那里,(我之后举得列子是放在持久化map[ConcurrentHashMap])

   2)、既然是续传,那么肯定需要一个结束的状态的标识,来告诉续传的文件,我已经执行完了。

   下面是关键代码:

    (1),ConcurrentHashMap

     ConcurrentHashMap的优点:

    ConcurrentHashMap允许一边更新、一边遍历,也就是说在Iterator对象遍历的时候,

    ConcurrentHashMap也可以进行remove,put操作,且遍历的数据会随着remove,put操作产出变化,也就是说在Iterator对象遍历的时候,ConcurrentHashMap也可以进行remove,put操作,且遍历的数据会随着remove,put操作产出变化。

    简单来说:它只对put,remove操作使用了同步操作,get操作并不影响

    代码如下:

package ga.gaapi.config;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

public class ZjHashMap {
    static Map<String,Long> conMap = new ConcurrentHashMap<>();
    //新增
    public static void addMap(String key,Long value){
        conMap.put(key,value);
    }
    //删除
    public  static void delect(String key){
        conMap.remove(key);
    }

    //获取
    public static  Long get(String key){
        return  conMap.get(key);
    }

}

(2)、读取文件部分核心代码:

path :路径,

fileName:文件名。

try{    

    File file = new File(path+"\\"+fileName);
    RandomAccessFile raf = new RandomAccessFile(file,"r");
    long count = file.length();
    byte[] read = new byte[Integer.parseInt(size)];
    int len =0;
    long fy = 0;
    long flag = 1;

     //判断标识中是否有值,有值的话,作为读取的首值
     if (null!= ZjHashMap.get(fileName)){
        raf.seek(ZjHashMap.get(fileName));
        //计算要分页的数量,用来判断是否已经全部读取
        fy = PostUtils.fy(count-ZjHashMap.get(fileName), Long.parseLong(size));
     }else{
        //计算要分页的数量,用来判断是否已经全部读取
        fy = PostUtils.fy(count, Long.parseLong(size));
     }
          while((len=raf.read(read))!=-1){
            ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
            outputStream.write(read,0,len);
            outputStream.flush();
            //读取的字节
            byte[] bytes = outputStream.toByteArray();

            //把字节数发送给续传文件方

            //当前字节数目
            ZjHashMap.addMap(fileName,raf.getFilePointer());
              if (flag == fy){
                 //表示已到结尾,可以将这部分逻辑发送给续传文件方,告诉它已续传完毕
              }
            flag ++;
            outputStream.close();
         }
     raf.close();
     ZjHashMap.delect(fileName);

}catch (Exception e){

           
}

、续传的文件

续传的文件就好说了,只要给一个续传的标识位置,和对应的字节流就可以了,代码如下:

filePath:生成的文件,用来续传用

content:将要写入的字节

position:续传的字节位置

 RandomAccessFile raf = null;
        try {
            raf = new RandomAccessFile(filePath, "rw"); //将随机存取文件流连接到文件,访问方式设置为可读可写
            raf.seek(position); //指定插入的位置
            raf.write(content); //插入指定内容
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //关闭随机存取文件流
            try {
                raf.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }