回顾在《即拿即用-Android单线程断点下载》下载的过程:

  1. 点击开始
  2. 开启一个网络连接获取文件长度
  3. 获取上一次下载进度
  4. 开启一个下载任务 ,起点是上一次的下载进度
  5. 每500毫秒发送一个广播通知界面更新进度
  6. 点击暂停的时候保存下载进度

在下载的时候,我们发现用RandomAccessFile替代了OutputStream,下面对比一下两者的使用区别:

在普通的下载中使用的是OutputStream

input = connection.getInputStream();//设置输出文件路径
output = new FileOutputStream(file);byte data[] = new byte[4096];
int count = -1;while ((count = input.read(data)) != -1) {output.write(data, 0, count);}

在断点下载中使用的是RandomAccessFile

input = connection.getInputStream();// 设置下载文件开始到结束的位置(结束的位置也就是文件的长度)conn.setRequestProperty("Range", "bytes=" + start + "-" + threadInfo.getEnd());//设置输出文件路径
raf = new RandomAccessFile(file, "rwd");
raf.seek(start);byte[] data= new byte[1024];
int count = -1;
while ((count = input.read(data)) != -1) {raf.write(data, 0, len);
}

今天的主角是RandomAccessFile

RandomAccessFile

 支持任意访问的方式,程序可以直接跳到任意地方来读写数据

RandomAccessFile属性

 RandomAccessFile 是随机访问文件(包括读/写)的类。它支持对文件随机访问的读取和写入,即我们可以从指定的位置读取/写入文件数据。

 需要注意的是,RandomAccessFile 虽然属于java.io包,但它不是InputStream或者OutputStream的子类;它也不同于FileInputStream和FileOutputStream。 FileInputStream 只能对文件进行读操作,而FileOutputStream 只能对文件进行写操作;但是,RandomAccessFile 同时支持文件的读和写,并且它支持随机访问

RandomAccessFile 函数列表

RandomAccessFile(File file, String mode)
RandomAccessFile(String fileName, String mode)void     close()
synchronized final FileChannel     getChannel()
final FileDescriptor     getFD()
long     getFilePointer()
long     length()
int     read(byte[] buffer, int byteOffset, int byteCount)
int     read(byte[] buffer)
int     read()
final boolean     readBoolean()
final byte     readByte()
final char     readChar()
final double     readDouble()
final float     readFloat()
final void     readFully(byte[] dst)
final void     readFully(byte[] dst, int offset, int byteCount)
final int     readInt()
final String     readLine()
final long     readLong()
final short     readShort()
final String     readUTF()
final int     readUnsignedByte()
final int     readUnsignedShort()
void     seek(long offset)
void     setLength(long newLength)
int     skipBytes(int count)
void     write(int oneByte)
void     write(byte[] buffer, int byteOffset, int byteCount)
void     write(byte[] buffer)
final void     writeBoolean(boolean val)
final void     writeByte(int val)
final void     writeBytes(String str)
final void     writeChar(int val)
final void     writeChars(String str)
final void     writeDouble(double val)
final void     writeFloat(float val)
final void     writeInt(int val)
final void     writeLong(long val)
final void     writeShort(int val)
final void     writeUTF(String str)

RandomAccessFile模式说明

 RandomAccessFile共有4种模式:”r”, “rw”, “rws”和”rwd”。

"r" 以只读方式打开。调用结果对象的任何 write 方法都将导致抛出 IOException。"rw" 打开以便读取和写入。"rws" 打开以便读取和写入。相对于 "rw","rws" 还要求对“文件的内容”或“元数据”的每个更新都同步写入到基础存储设备。 "rwd" 打开以便读取和写入,相对于 "rw","rwd" 还要求对“文件的内容”的每个更新都同步写入到基础存储设备。

 说明:

(01) 什么是“元数据”,即metadata?

 英文解释如下:

The definition of metadata is "data about other data." With a file system, the data is contained in its files and directories, and the metadata tracks information about each of these objects: Is it a regular file, a directory, or a link? What is its size, creation date, last modified date, file owner, group owner, and access permissions?

 大致意思是:

 metadata是“关于数据的数据”。在文件系统中,数据被包含在文件和文件夹中;metadata信息包括:“数据是一个文件,一个目录还是一个链接”,“数据的创建时间(简称ctime)”,“最后一次修改时间(简称mtime)”,“数据拥有者”,“数据拥有群组”,“访问权限”等等。

(02) “rw”, “rws”, “rwd” 的区别。

 当操作的文件是存储在本地的基础存储设备上时(如硬盘, NandFlash等),”rws” 或 “rwd”, “rw” 才有区别。

 当模式是 “rws” 并且 操作的是基础存储设备上的文件;那么,每次“更改文件内容[如write()写入数据]” 或 “修改文件元数据(如文件的mtime)”时,都会将这些改变同步到基础存储设备上。

 当模式是 “rwd” 并且 操作的是基础存储设备上的文件;那么,每次“更改文件内容[如write()写入数据]”时,都会将这些改变同步到基础存储设备上。

 当模式是 “rw” 并且 操作的是基础存储设备上的文件;那么,关闭文件时,会将“文件内容的修改”同步到基础存储设备上。至于,“更改文件内容”时,是否会立即同步,取决于系统底层实现。

 RandomAccessFile是用来访问那些保存数据记录的文件的,你就可以用seek( )方法来访问记录,并进行读写了。这些记录的大小不必相同;但是其大小和位置必须是可知的。但是该类仅限于操作文件。

和其它的I/O类的对比

 RandomAccessFile能在文件里面前后移动,所以它的行为与其它的I/O类有些根本性的不同。总而言之,它是一个直接继承Object的,独立的类

 RandomAccessFile的工作方式是,把DataInputStream和DataOutputStream结合起来,再加上它自己的一些方法,比如定位用的getFilePointer( ),在文件里移动用的seek( ),以及判断文件大小的length( )、skipBytes()跳过多少字节数。此外,它的构造函数还要一个表示以只读方式(“r”),还是以读写方式(“rw”)打开文件的参数 (和C的fopen( )一模一样)。它不支持只写文件。

 只有RandomAccessFile才有seek搜寻方法,而这个方法也只适用于文件。

memory-mapped files

 RandomAccessFile的绝大多数功能,但不是全部,已经被JDK 1.4的nio的”内存映射文件(memory-mapped files)”给取代了,你该考虑一下是不是用”内存映射文件”来代替RandomAccessFile了。

例子

 利用RandomAccessFile实现文件的多线程下载,即多线程下载一个文件时,将文件分成几块,每块用不同的线程进行下载。下面是一个利用多线程在写文件时的例子,其中预先分配文件所需要的空间,然后在所分配的空间中进行分块,然后写入:

import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;/*** 测试利用多线程进行文件的写操作*/
public class Test {public static void main(String[] args) throws Exception {// 预分配文件所占的磁盘空间,磁盘中会创建一个指定大小的文件RandomAccessFile raf = new RandomAccessFile("D://abc.txt", "rw");raf.setLength(1024*1024); // 预分配 1M 的文件空间raf.close();// 所要写入的文件内容String s1 = "第一个字符串";String s2 = "第二个字符串";String s3 = "第三个字符串";String s4 = "第四个字符串";String s5 = "第五个字符串";// 利用多线程同时写入一个文件new FileWriteThread(1024*1,s1.getBytes()).start(); // 从文件的1024字节之后开始写入数据new FileWriteThread(1024*2,s2.getBytes()).start(); // 从文件的2048字节之后开始写入数据new FileWriteThread(1024*3,s3.getBytes()).start(); // 从文件的3072字节之后开始写入数据new FileWriteThread(1024*4,s4.getBytes()).start(); // 从文件的4096字节之后开始写入数据new FileWriteThread(1024*5,s5.getBytes()).start(); // 从文件的5120字节之后开始写入数据}// 利用线程在文件的指定位置写入指定数据static class FileWriteThread extends Thread{private int skip;private byte[] content;public FileWriteThread(int skip,byte[] content){this.skip = skip;this.content = content;}public void run(){RandomAccessFile raf = null;try {raf = new RandomAccessFile("D://abc.txt", "rw");raf.seek(skip);raf.write(content);} catch (FileNotFoundException e) {e.printStackTrace();} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();} finally {try {raf.close();} catch (Exception e) {}}}}}

 另外我们可以用RandomAccessFile这个类,来实现一个多线程断点下载的功能,用过下载工具的朋友们都知道,下载前都会建立两个临时文件,一个是与被下载文件大小相同的空文件,另一个是记录文件指针的位置文件,每次暂停的时候,都会保存上一次的指针,然后断点下载的时候,会继续从上一次的地方下载,从而实现断点下载或上传的功能,有兴趣的朋友们可以自己实现下。

 更多java io系列的文章系列可以参考《java io系列01之 “目录”》
 
《即拿即用-Android单线程断点下载》

《断点下载神器-RandomAccessFile》

《即拿即用-Android多线程断点下载》

参考

  • Java RandomAccessFile用法

  • Java IO的RandomAccessFile的使用

  • java io系列26之 RandomAccessFile

断点下载神器-RandomAccessFile相关推荐

  1. 即拿即用-Android多线程断点下载

    线程下载只需要确定好下载一个文件需要多少个线程,一般来说最好为3条线程,因为线程过多会占用系统资源,而且线程间的相互竞争也会导致下载变慢. 其次下载的时候将文件分割为三份(假设用3条线程下载)下载,在 ...

  2. Aria2打造属于自己的下载神器

    请关注微信公众号( ?sharingplus) 我使用Aria2差不多已经2年了.在这段时间使用很多下载工具,最开始使用的是迅雷极速版 .后面各种原因不好使了.Free Download Manage ...

  3. Java多线程断点下载

    多线程下载已经提高了下载的效率,但是当一些特殊情况发生的时候,我们需要对程序进行处理,这样效率会更高.比如,断电断网等造成下载中断,那么我们下一次又要重新开始下载,这样效率底下,所以我们可以考虑使用断 ...

  4. android 断点下载的实现,Android实现断点下载的方法

    最近做的项目中需要实现断点下载,即用户一次下载可以分多次进行,下载过程可以中断,在目前大多数的带离线缓存的软件都是需要实现这一功能.本文阐述了通过sqlite3简单实现了一个具有断点下载功能的demo ...

  5. edge 此项内容已下载并添加到 Chrome 中。_比肩迅雷的下载神器大盘点

    迅雷对于大家来说都不陌生,但是如今的迅雷要是不开会员,下载速度简直不能直视.而且,现在使用迅雷下载一些电影或音乐时还会出现"版权方要求无法下载",让人很是头疼.那么除了迅雷以外,还 ...

  6. 推荐一个下载神器(官网资料下载必备)

    来源:公众号[鱼鹰谈单片机] 作者:鱼鹰Osprey ID   :emOsprey 很多时候,我们需要在官网下载一些东西,比如 KEIL 官网的安装包, STM32 官网的软件包,等等.这些包都有一个 ...

  7. Android 多线程断点下载demo实现

    先来一张效果图: 主要实现思路: 每一个下载都是通过RandomAccessFile对下载资源的总长进行切割之后,根据我们设置的线程多少进行计算之后开启多线程下载的.而每一个任务都是一个AsyncTa ...

  8. android 多线程断点下载,listview 模式 开始 暂停等功能

    android 多线程断点下载,listview 模式 代码依次如下: 布局: <?xml version="1.0" encoding="utf-8"? ...

  9. java 下载暂停实现_Java实现多线程断点下载(下载过程中可以暂停)

    线程可以理解为下载的通道,一个线程就是一个文件的下载通道,多线程也就是同时开启好几个下载通道.当服务器提供下载服务时,使用下载者是共享带宽的,在优先级相同的情况下,总服务器会对总下载线程进行平均分配. ...

  10. java1.7线程暂停_Java实现多线程断点下载实例代码(下载过程中可以暂停)

    线程可以理解为下载的通道,一个线程就是一个文件的下载通道,多线程也就是同时开启好几个下载通道.当服务器提供下载服务时,使用下载者是共享带宽的,在优先级相同的情况下,总服务器会对总下载线程进行平均分配. ...

最新文章

  1. python中系列的含义_一篇文章让你彻底搞清楚Python中self的含义
  2. App Engine中的Google Services身份验证,第2部分
  3. 化繁为简:数据库运维人员应该知道这些...
  4. 图像处理保研面试_细思极妙的保研面试经验汇总?这些小技巧太加分了吧
  5. 农行银行添加卡信息服务器,说说农业银行为App我的帐户设置里没有显示借记卡添加...
  6. android卸载弹出窗口,卸载Android app弹出浏览器的一种实现
  7. angular dynamic component 笔记
  8. protues 学习
  9. DHCP报文及其格式
  10. android pc投屏,安卓投屏助手pc版
  11. 使用proc编译器遇到的几个问题及解决办法
  12. 电脑桌面文件不见了怎么恢复?
  13. Ubuntu下解压rar压缩文件
  14. 使用AirCrack破解wifi密码(wpa/wpa2)
  15. 理解线性代数,矩阵运算,行列式
  16. 设计模式-----装饰模式.
  17. BeautifulSoup安装
  18. 20220712 初识JS
  19. R语言ggplot2可视化气泡图(bubble plot)、将可视化图像的图例(lengend)放置在图像底部、图例水平方向排布(horizontal direction)、图例标题在图例标签顶部
  20. 【原创】JavaWeb仓库管理系统(Web仓库管理系统毕业设计)

热门文章

  1. 人工智能、机器学习、神经网络及深度学习关系
  2. win10cmd计算机管理界面,Win10命令提示符cmd在哪 Win10以管理员身份运行方法
  3. 【Android病毒分析报告】- 手机支付毒王“银行悍匪”的前世今生
  4. 象棋人机对战中所用的极大极小值-alpha-beta剪枝算法介绍
  5. win10环境下matlab2017b编译运行c++文件步骤
  6. 神经网络的双曲线正切激活函数
  7. [渝粤教育] 苏州科技大学 混凝土结构设计原理 参考 资料
  8. iOS 视频播放器 VLC的集成和基本使用
  9. j2ee02 集合框架
  10. 3dmax渲染完就卡住不动,怎么办