RandomAccessFile 随机存取文件流
专门用来读写文件数据的类,其基本指针对文件进行随机访问
-
RandomAccessFile 声明在java.io包下,但直接继承于java.lang.Object类。并且它实现了DataInput、DataOutput这两个接口,意味着这个类既可以读也可以写。
-
RandomAccessFile 类支持 “随机访问” 的方式,程序可以直接跳到文件的任意地方来读、写文件
支持只访问文件的部分内容
可以向已存在的文件后追加内容 (指定指针位置 ,可以向文件写入内容)
RandomAccessFile 对象包含一个记录指针,用以标示当前读写处的位置。RandomAccessFile 类对象可以自由移动记录指针:
-
long getFilePointer():获取文件记录指针的当前位置
-
void seek(long pos):将文件记录指针定位到 pos 位置,当什么都不写时,第一次操作文件默认从0开始读写文件数据。指针会随着操作而改变位置
指针操作的单位是字节。
RandomAccessFile常用构造器
-
public RandomAccessFile (File file, String mode)
用指定的文件名来创建一个随机存取文件对象,指定访问模式: -
public RandomAccessFile (String filepathname, String mode);
用指定的文件路径来创建一个随机存取文件对象,指定访问模式。
访问模式有以下:
“ r ”: 可读,当指定文件不存在时不会创建新文件,编译不会报错,运行时会报文件找不到异常(FileNotFoundException)
" rw ": 可读可写,当指定文件不存在时,会创建新文件
“rwd”: 打开以便读取和写入;同步文件内容的更新
“rws”: 打开以便读取和写入;同步文件内容和元数据的更新
创建RandomAccessFile对象
想要实现对文件随机读写操作,必须声明一个随机访问文件的对象,并为其指定访问模式。通过对象可以调用RandomAccessFile类 的一些常用方法实现对文件更好的读写
RandomAccessFile raf = new RandomAccessFile(File file , String mode);
RandomAccessFile raf = new RandomAccessFile(String filepathname , String mode);
常用方法
需要注意:每次访问完对象文件时,指针都会发生相应的改变,若想读之前的内容,必须重新给指针赋值。
void close() ; 关闭此随机访问文件流并释放与该流关联的所有系统资源。
当流关闭之后不能再继续写出 ,
否则会抛出IO异常: java.io.IOException:Stream Closed
注意 ** : 程序中打开的文件 IO 资源不属于内存里的资源,垃圾回收机制无法回收该资源,所以应该显式关闭文件 IO 资源。
long getFilePointer() ;返回此文件中的当前偏移量(当前指针位置(指向第几个字节))
void seek(long pos)
设置到此文件开头测量到的文件指针偏移量,在该位置发生下一个读取或写入操作。
long length() ;返回此文件的长度(字节数)。
int read() ; 从此文件中读取一个数据字节。
读取一个字节并以int形式返回(读取的数据再int值对应的二进制的低八位上)
如果返回的int值为-1则表示读到了文件末尾
int read(byte[] b) ;
将最多 b.length 个数据字节从此文件读入 byte 数组。
一次性从文件中读取给定的字节数组总长度的字节量,并存入到该数组中,
返回值为实际读取到的字节量,如果返回值-1则表示文件末尾
int read(byte[] b, int off, int len);
从该文件指定起始位置off将最多 len 个数据字节从此文件读入 byte 数组。
String readLine() ; 从此文件读取文本的下一行。
void setLength(long newLength) ; 设置此文件的长度。
一次性写多个字节
void write(byte[] b)
将 b.length 个字节从指定 byte 数组写入到此文件,并从当前文件指针开始。
一次性将给定的字节数组中的所有字节写入文件。
void write(byte[] b, int off, int len)
将 len 个字节从指定 byte 数组写入到此文件,并从偏移量 off 处开始。
将给定的字节数组从下标offset处连续len个字节一次性写出到目标文件
void write(byte[] data ,int offset,int raf.read(data))
从指定位置写入实际的字节数。
void write(int b) ;向此文件写入指定的字节。
虽然参数是int型,但是写入时并不能完整的将int型数据写入文件,
只能从文件中写入1个字节,写入到是给定的int值参数对应的二进制的“低八位”
写入int型参数可以用WriteInt()
void writeInt(int v)
按四个字节将 int 写入该文件,先写高字节。
void writeLong(long v) ;按八个字节将 long 写入该文件,先写高字节。
writeDouble(double v)
使用 Double 类中的 doubleToLongBits 方法将双精度参数转换为一个 long,
然后按八字节数量将该 long 值写入该文件,先定高字节。
因为 write() 都只能操作字节,所以当需要写入(从程序写入文件)字符串时需要将字符串转换为byte[] 数组。用到如下方法。
byte[] getBytes(),将字符串按照系统默认的编码集转换为byte[]数组.(编码集和字符集一个意思)
byte[] getBytes(String charsetName),将字符串按照指定的字符集转化为byte[]数组
//写入用户名:
byte[] data = username.getBytes("UTF-8");//getBytes()使用默认的编码,
想要指定编码格式,使用重载方法getBytes(String charsetName)
//System.out.println(Arrays.toString(data));//byte[] data = username.getBytes(),[115, 97, 116, 106]
//将数组扩容至32字节,浅层复制,更换引用的指向
data = Arrays.copyOf(data,32);
raf.write(data);//写入32字节
//写入密码,先将密码转成byte数组,
data = password.getBytes("UTF-8");
data = Arrays.copyOf(data,32);
raf.write(data);
因为 read() 都只能操作字节,所以当需要读出(从文件读出到程序中)文件数据时需要将byte[] 数组,转换为字符串形式(String)并且可以指定编码集。用到以下方法。
String类提供了一个构造方法:
-
String(byte bytes[], String charsetName)
将指定的byte数组中的数据按照指定的字符集转换为字符串
注意:将byte数组转换为String,指定编码集,byte的默认值空格转换为String 会转成空白,可以直接调用trim()去掉两边的空白
想要将文件中的数据以字符串的形式输出需要创建字符串对象,指定字符集。
//将byte数组转换为String,指定编码集,byte的默认值空格转换为String 会转成空白,可以直接调用trim()去掉两边的空白
String username = new String(data,"UTF-8").trim();
//读取密码
data = new byte[32];
raf.read(data);
String password = new String(data,"UTF-8").trim();
//读取昵称
data = new byte[32];
raf.read(data);
String nickname = new String(data,"UTF-8").trim();
//读取年龄
int age = raf.readInt();
System.out.println("username :" + username + " ,password : " + password +" ,nickname :" + nickname +" ,age :"+ age);
//System.out.println(Arrays.toString(data));
System.out.println(raf.getFilePointer());
补充:编码集
UTF-8 :万国码。一个字节,中文占三个字节
GBK : 国标编码(中国家标准),英文占1字节,中文占 2字节。
ISO8859-1 :欧洲字符集,网络传输用的是ISO8859-1,不支持中文
编码:字符串->字节数组
解码:字节数组->字符串
当我们将字符串按照指定字符集转换为字节时,如果字符集名字拼写有误,则会抛出异常: java.io.UnsupportedEncodingException
RandomAccessFile raf = new RandomAccessFile("raf.txt","r");
//创建一个与文件等长的字符数组,raf.length()返回值是一个long型。
byte[] data = new byte[(int)raf.length()];
//一次性将文件中的所有字节读入字节数组
raf.read(data);
//想要将文件中的数据以字符串的形式输出需要创建字符串对象,指定字符集。
String str = new String(data,"UTF-8");
System.out.println(str);
//关流,为避免内存浪费。
raf.close();
RandomAccessFile 如何基于指针读写文件?
① 声明随机读写文件对象,两种方式(两种构造方法),指定文件访问模式
例:
方式一:使用指定路径
RandomAccessFile raf = new RandomAccessFile(String filepathname , String mode)
方式二:使用文件
RandomAccessFile raf = new RandomAccessFile(File file , String mode);
② 使用read() 及重载方法 read(byte[] b), read(byte[] b,int off , int len);将文件中的内容按照指定长度读出存储到 byte[] 数组中
③ 使用write(byte []) 及重载方法write(byte[] b,int off, int len);将byte[] 数组中的数据写入当前指定的文件。
④ 使用seek(long pos) 指定指针位置实现访问文件任意位置数据。如果访问的位置不在文件有效字节范围内会抛异常。