RandomAccessFile是Java输入/输出流中功能最丰富的文件内容访问类,既可以做输入流,也可以做输出流。与普通的输入/输出流不同的是,RandomAccessFile支持跳到文件任意位置读写数据,RandomAccessFile对象包含一个记录指针,用以标识当前读写处的位置,当程序创建一个新的RandomAccessFile对象时,该对象的文件记录指针对于文件头(也就是0处),当读写n个字节后,文件记录指针将会向后移动n个字节。我们可以用RandomAccessFile很方便来实现断点续传,以前断点续传大部分都先由前端分割,然后后台记录每一片的顺序,最后按顺序合并,利用RandomAccessFile可以直接在后台对文件进行续写。
RandomAccessFile类在创建对象时,除了指定文件存储路径,还需要指定一个mode参数,该参数指定RandomAccessFile的访问模式,该参数有如下四个值:
r:以只读方式打开指定文件。如果试图对该RandomAccessFile指定的文件执行写入方法则会抛出IOException
rw:以读取、写入方式打开指定文件。如果该文件不存在,则尝试创建文件
rws:以读取、写入方式打开指定文件。相对于rw模式,还要求对文件的内容或元数据的每个更新都同步写入到底层存储设备,默认情形下(rw模式下),是使用buffer的,只有cache满的或者使用RandomAccessFile.close()关闭流的时候儿才真正的写到文件
rwd:与rws类似,只是仅对文件的内容同步更新到磁盘,而不修改文件的元数据
public RandomAccessFile(String name, String mode) throws FileNotFoundException{ this(name != null ? new File(name) : null, mode);}public RandomAccessFile(File file, String mode) throws FileNotFoundException { String name = (file != null ? file.getPath() : null); int imode = -1; if (mode.equals("r")) imode = O_RDONLY; else if (mode.startsWith("rw")) { imode = O_RDWR; rw = true; if (mode.length() > 2) { if (mode.equals("rws")) imode |= O_SYNC; else if (mode.equals("rwd")) imode |= O_DSYNC; else imode = -1; } } if (imode < 0) throw new IllegalArgumentException("Illegal mode \"" + mode + "\" must be one of " + "\"r\", \"rw\", \"rws\"," + " or \"rwd\""); SecurityManager security = System.getSecurityManager(); if (security != null) { security.checkRead(name); if (rw) { security.checkWrite(name); } } if (name == null) { throw new NullPointerException(); } if (file.isInvalid()) { throw new FileNotFoundException("Invalid file path"); } fd = new FileDescriptor(); fd.attach(this); path = name; open(name, imode); } //常量值 private static final int O_RDONLY = 1; private static final int O_RDWR = 2; private static final int O_SYNC = 4; private static final int O_DSYNC = 8;
我们来看一下比较典型几个方法:
1、seek:指定文件的光标位置,通俗点说就是指定你的光标位置
然后下次读文件数据的时候从该位置读取。
2、length:文件的长度,返回long类型。
注意它并不会受光标的影响。只会反应客观的文本长度。
3、write:输出流,接收文件字节。输出之前先调seek,会从指定位置输出。
这是最断点续传最典型三个方法,下面来看看代码:
//创建RandomAccessFile对象RandomAccessFile outputFile = new RandomAccessFile(filePath+fileName,"rw");//指定位置outputFile.seek(doc_start==0);//输出文件并记录长度outputFile.write(file.getBytes());fileSize=outputFile.length();
断点下载如下:
RandomAccessFile outputFile = new RandomAccessFile(filePath+fileName,"r"); //要下载的字节数content = new byte[length];//从starart位置开始下载outputFile.seek(start);outputFile.read(content);