前言:
今天了解了一下断点续传,先记录一下,可能了解的不是特别全面,主要是看网上的实现。
正文:
根据了解其主要实现是两种吧,一种是
断点续传可以通过使用RandomAccessFile(随机访问文件)专门处理文件的类,里面有seek方法和skipBytes()方法可以移动文件指针具体,可以自行了解,另外也可以使用InputStream,里面有一个skip方法可以移动文件指针。实现思路就是每次传输时用缓冲区,每次写入记录当前已经传输的大小,然后保存,暂停时将记录和对应文件永久保存(数据库,文件等)。下次传输时用seek或者skip函数移动指针再读取传输。
关于RandomAccessFile
“r”:以只读的方式打开,调用该对象的任何write(写)方法都会导致IOException异常
“rw”:以读、写方式打开,支持文件的读取或写入。若文件不存在,则创建之。
“rws”:以读、写方式打开,与“rw”不同的是,还要对文件内容的每次更新都同步更新到潜在的存储设备中去。这里的“s”表示synchronous(同步)的意思
“rwd”:以读、写方式打开,与“rw”不同的是,还要对文件内容的每次更新都同步更新到潜在的存储设备中去。使用“rwd”模式仅要求将文件的内容更新到存储设备中,而使用“rws”模式除了更新文件的内容,还要更新文件的元数据(metadata),因此至少要求1次低级别的I/O操作。
关于skip和seek:
调用seek方法类定位大于文件长度的位置将导致IOException,与java.io.InputStream的skip()不同,seek可以定位到文件的任意位置,而skip只能相对于当前位置定位到另一个位置。seek方法是一个相对高开销的操作,需慎重使用,较好使用流数据来构建应用的访问模式。(摘自网络)
下面是两种模拟实现的代码,具体实现可以参考,之后尽量自己写一个javaweb的简单实现
博客1:使用的skip实现
博客2:使用的seek实现
第一种
/** * 测试实现文件断点续存 * 使用seek函数 * @author ht032 * */ public class TestFile { public static void main(String[] args) { // TODO Auto-generated method stub // File file = new File("d:/1.txt"); // File file = FileManage.CreateDir("d:/user.txt"); // FileManage.remove("d:/dir1"); try { int len = new TestFile().CopyFile("d:/lenet80.png", "d:/temp.png", 67584); System.out.print("已经上传:"+len/1024.0); System.out.println("KB\n"+len); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } private RandomAccessFile sourceFile; private RandomAccessFile targetFile; /** * 实现复制,需要首先设置source目标文件流 * * @param target 目标文件 * @param position 源文件的起始位置 * @return 返回当前已经传输的文件大小 */ public int CopyFile(String source, String target, long position) throws Exception { if (source == null) throw new Exception("source is null!"); byte[] buff = new byte[1024]; int len = 0; try { // 打开文件 targetFile = new RandomAccessFile(target, "rw"); sourceFile = new RandomAccessFile(source, "r"); //文件指针移动到指定位置 sourceFile.seek(position); targetFile.seek(position); long length = sourceFile.length(); System.out.printf("文件总大小%.2fKB\n", length / 1024.0); while (true) { // int read = rafilein.read(buff); int read = sourceFile.read(buff); targetFile.write(buff); len += read; if (len >= length/2 ||read<0) break; } } catch (FileNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } finally { // 打开日志文件 // FileWriter log=new FileWriter(logPath); // log.write(str); try { sourceFile.close(); targetFile.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } return len; } }
第二种
package FileDemo; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.RandomAccessFile; public class TestFile2 { public static void main(String[] args) { // TODO Auto-generated method stub try { int len = new TestFile2().CopyFile("d:/lenet80.png", "d:/temp.png", 11264); System.out.print("已经上传:"+len/1024.0); System.out.println("KB\n"+len); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } private InputStream sourceFile; //这里客户端模拟续存也可使用RandomAccessFile // private RandomAccessFile targetFile; private OutputStream targetFile; /** * 实现复制,需要首先设置source目标文件流 * 使用skip * @param target 目标文件 * @param position 源文件的起始位置 * @return 返回当前已经传输的文件大小 */ public int CopyFile(String source, String target, long position) throws Exception { if (source == null) throw new Exception("source is null!"); byte[] buff = new byte[1024]; int len = 0; try { // 打开文件,在后面追加 实现断点续存 targetFile = new FileOutputStream(target,true); sourceFile = new FileInputStream(source); //文件指针移动到指定位置 sourceFile.skip(position); // long length = sourceFile.length(); // System.out.printf("文件总大小%.2fKB\n", length / 1024.0); while (true) { // int read = rafilein.read(buff); int read = sourceFile.read(buff); targetFile.write(buff); len += read; if( read<0 //leng>4*1024//先传输4KB ) break; } } catch (FileNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } finally { // 打开日志文件 // FileWriter log=new FileWriter(logPath); // log.write(str); try { sourceFile.close(); targetFile.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } return len; } }
来源:51CTO
作者:慌逃
链接:https://blog.csdn.net/qq_36414969/article/details/100738258