JAVA中RandomAccessFile
一.RandomAccessFile的基本介绍:
RandomAccessFile
- 该类基于指针用来读写文件数据
- 创建RandomAccessFile常用的构造方法:
- RandomAccessFile(String path,String mode)
- RandomAccessFile(File file,string mode)
- 第一个参数是要进行读写的文件
- 第二个参数为权限
- r:只读模式 例如: RandomAccessFile raf=new RandomAccessFile(file, “r”);
- rw:读写模式 例如:RandomAccessFile raff=new RandomAccessFile(“demo2.txt”, “rw”);
二:RandomAccessFile的读写操作
1.写:
1.创建 RandomAccessFile文件,向文件中写入a。
public class RandomAccessFileWriteDemo {
public static void main(String[] args) throws IOException {
//方式一:RandomAccessFile(String path,String mode)
// File file=new File("./demo");
// RandomAccessFile raf=new RandomAccessFile(file, "r");
// System.out.println("执行完毕");
//方式二:RandomAccessFile(File file,string mode)
RandomAccessFile raff=new RandomAccessFile("demo2.txt", "rw");
System.out.println("执行完毕!");
/*
* RandomAccessFile提供了void write(int d),
* 向文件中写入一个字节数据,写的是给定int值所对应的二进制的”低八位“
* 000000000 00000000 00000000 00000001
*
* 例如:97转为二进制11000011,由于常用编译器会在开的时候,
* 将字节显示,查询ASCII编码,会显示a,其他值则查询系统默认的码
*/
raff.write(65);
System.out.println("写入完毕!");
/*
* RandomAccessFile在文件访问的操作全部结束的时候,要调用close()方法来
* 释放所有系统资源
*/
raff.close();
}
}
2.设置指针位置;
RandomAccessFile提供了一个方法seek(int n),设置指针位置.
RandomAccessFile提供了一个方法getFilePointer(),获取指针位置.
public class RandomAccessFileWriteDemo2 {
public static void main(String[] args) throws IOException {
String str="hello";
//将字符串转换为字节
byte[] b=str.getBytes();
RandomAccessFile raff=new RandomAccessFile("demo.txt", "rw");
//设置指针位置,RAF提供了获取指针位置的方法seek()
raff.seek(10);//设置指针位置5,追加字符串world
//获取指针的位置(游标位置)RAF提供了获取指针位置的方法getFilePointer()返回long
long p=raff.getFilePointer();
System.out.println("写入前的位置:"+p);//10
raff.write(b);
System.out.println("写入完毕!!!!");
p=raff.getFilePointer();//15
System.out.println("写入后的指针位置:"+p);
raff.close();
}
}
3.字符集;
- 按照系统默认字符集转换(不推荐,因为存在平台差异)
- byte[] getBytes(String scan) scan:字符集
- 按照给定的字符集转换,字符集的名字不区分大小写;
- GBK:国际编码,中文占2个字节
- UTF-8:也称万国码,中文占3个字节
- ISO8859-1:欧洲字符集,不支持中文。
public class RandomAccessFileWriteDemo3 {
public static void main(String[] args) throws IOException {
RandomAccessFile raf=new RandomAccessFile("demo2.txt", "rw");
String str="你好,树先生";
byte[] b=str.getBytes("UTF-8");//将字符串转换为字节
System.out.println(b.length);//18
raf.write(b);
System.out.println("输入完毕!!");
raf.close();
}
}
2.读:
1.使用RandomAccessFile读取文件中的数据(字节读取);
RandomAccessFile提供了read()方法,返回int。
public class RandomAccessFileReadDemo {
public static void main(String[] args) throws IOException {
RandomAccessFile raf=new RandomAccessFile("demo.txt","r");
int len=-1;//保存读取到的每一个字节
while((len=raf.read())!=-1){//数据读到-1时则读到文件的末尾
System.out.print((char)len);
}
raf.close();
}
}
2.块读取一:
public class RandomAccessFileReadDemo2 {
public static void main(String[] args) throws IOException {
RandomAccessFile raf=new RandomAccessFile("demo2.txt", "r");
byte[] bs=new byte[100];
int n=raf.read(bs);//读取100个字节并存放在bs字节数组中,返回的是实际读到的字节数据量
System.out.println(n);
//把读取出来的字节转换为字符串
String str=new String(bs,"gbk");
System.out.println(str);
raf.close();
}
}
该读取的弊端是读取出来的字符串长度是100,浪费空间大小。
3.块读取二:
string有构造方法string(byte[] b,int offset,int len ,string scn);
将给定的字节数组从下标offset连续读取len个。
public class RandomAccessFileReadDemo3 {
public static void main(String[] args) throws IOException {
RandomAccessFile raf=new RandomAccessFile("demo2.txt","r");
byte[] bs=new byte[100];
int len=raf.read(bs);
System.out.println(len);
String str=new String(bs,0,len,"UTF-8");
System.out.println(str);
raf.close();
}
}
这种读取快,并且读到的是字符串真实的长度,不会浪费内存空间。
三.用RandomAccessFile进行MP3的复制
1.使用指针读写
public class RandomAccessFile_copyMP3Demo {
public static void main(String[] args) throws IOException {
RandomAccessFile raf_r=new RandomAccessFile("D:/CloudMusic/Against the Current - Legends Never Die.mp3","r");
RandomAccessFile raf_w=new RandomAccessFile("D:/CloudMusic/复制后的Against the Current - Legends Never Die.mp3","rw");
long time1=System.currentTimeMillis();//获取当前时间的毫秒数
System.out.println("正在复制中....");
int len=-1;
while((len=raf_r.read())!=-1){
raf_w.write(len);
}
long time2=System.currentTimeMillis();//获取当前时间的毫秒数
System.out.println("复制所需要的毫秒数"+(time2-time1)/1000+"秒");
raf_r.close();
raf_w.close();
}
}
2.使用块读写
public class RandomAccessFile_copyMP3Demo2 {
public static void main(String[] args) throws IOException {
RandomAccessFile raf_r=new RandomAccessFile("D:/CloudMusic/Against the Current - Legends Never Die.mp3", "r");
RandomAccessFile raf_w=new RandomAccessFile("D:/CloudMusic/复制第3次后的Against the Current - Legends Never Die.mp3", "rw");
byte[] bs=new byte[1024*10];
int len=-1;
long p1=System.currentTimeMillis();
System.out.println("正在复制。。");
while((len=raf_r.read(bs))!=-1){
raf_w.write(bs,0,len);
}
System.out.println("复制完成。。");
long p2=System.currentTimeMillis();
System.out.println("复制时间为:"+(p2-p1));
raf_r.close();
raf_w.close();
}
}
结论:
由于硬盘的物理性,导致随机读写效率很低,因此我们推荐“块读写”;
块读写的效率很高,一次一组字节读写数据,所以若想着读写效率我们需要提高每次
读写的次数.
四.使用RandomAccessFile模拟数据库,进行增查改操作。
1.完成用户注册
- 用uer.dat文件保存用户信息
- 每个用户信息包括:用户名,密码,昵称,年龄
- 其中年龄用int类行,其他是字符串类型
public class RandomAccessFile_userRegister {
public static void main(String[] args) throws IOException {
RandomAccessFile raf=new RandomAccessFile("user.dat","rw");
raf.seek(raf.length());//设置指针位置
Scanner scanner=new Scanner(System.in);
String name=scanner.next();
String pwd=scanner.next();
String nick=scanner.next();
int age=scanner.nextInt();
//对数组进行扩容写入用户名
byte[] data=name.getBytes("UTF-8");
data=Arrays.copyOf(data,32);
raf.write(data);
//对数组进行扩容写入密码
data=pwd.getBytes();
data=Arrays.copyOf(data,32);
raf.write(data);
//对数组进行扩容写入昵称
data=nick.getBytes("UTF-8");
data=Arrays.copyOf(data,32);
raf.write(data);
//年龄
raf.writeInt(age);
System.out.println("写入完毕!!");
System.out.println(raf.getFilePointer());
//raf.close();
}
}
2.用户登录功能
如果登录成功显示该用户的所有信息;
public class RandomAccessFileUserlogin {
public static void main(String[] args) throws IOException {
RandomAccessFile raf=new RandomAccessFile("demo5.txt","r");
Scanner scanner=new Scanner(System.in);
System.out.println("账号输入:");
String user_name=scanner.next();
System.out.println("输入密码:");
String user_pwd=scanner.next();
byte[] bs=new byte[32];
boolean nameflag=false;
boolean pwdflag=false;
for(int i=0;i<raf.length()/100;i++){
raf.seek(i*100);//设置指针位置
System.out.println("指针位置:"+raf.getFilePointer());
raf.read(bs);//获取姓名
String name=new String(bs,"UTF-8").trim();
if(name.equals(user_name)){
System.out.println("账号正确!");
nameflag=true;
raf.read(bs);//获取密码
String pwd=new String(bs,"UTF-8").trim();
if(pwd.equals(user_pwd)){
System.out.println("密码输入正确!");
pwdflag=true;
System.out.println("登录成功!!");
raf.read(bs);//获取昵称
String nick=new String(bs,"utf-8");
int age=raf.readInt();
System.out.println("输出用户信息为"+name+","+pwd+","+nick+","+age);
}
break;
}
}
if(nameflag==false){
System.out.println("账号错误");
return;
}
if(pwdflag==false){
System.out.println("密码错误");
}
}
}
3.修改用户数据密码
前提是登陆成功才可以修改;
public class RandomAccessFileUserupdate {
public static void main(String[] args) throws IOException {
RandomAccessFile raf=new RandomAccessFile("demo9.txt","rw");
Scanner scanner=new Scanner(System.in);
System.out.println("请输入名字:");
String user_name=scanner.next();
System.out.println("请输入密码:");
String user_pwd=scanner.next();
byte[] data=new byte[32];
boolean nameflag=false;
boolean pwdflag=false;
for(int i=0;i<raf.length()/100;i++){
raf.seek(i*100);//设置指针位置
raf.read(data);//读取名字
String name=new String(data,"UTF-8").trim();
if(name.equals(user_name)){
System.out.println("用户名正确!");
nameflag=true;
raf.read(data);//读取密码
String pwd=new String(data,"UTF-8").trim();
if(pwd.equals(user_pwd)){
System.out.println("密码正确!!");
pwdflag=true;
System.out.println("密码修改:");
String newpwd=scanner.next();
raf.seek(i*100+32);//或者raf.seek(raf.getFilePointer()-32);
byte[] bs=newpwd.getBytes("UTF-8");
bs=Arrays.copyOf(bs,32);
raf.write(bs);//将新密码写入
System.out.println("密码修改成功!!!");
}
break;
}
}
if(nameflag==false){
System.out.println("用户名错误!");
return;
}
if(pwdflag==false){
System.out.println("密码错误!");
}
}
}
4.读取所有用户的数据
将读取出来的用户数据以格式name,pwd,nick,age输出;
public class RandomAccessFile_userRead {
public static void main(String[] args) throws IOException {
RandomAccessFile raf=new RandomAccessFile("user.dat","r");
byte[] bs=new byte[32];
for(int i=0;i<raf.length()/100;i++){
raf.read(bs);
//获取名字
String name=new String(bs,"utf-8").trim();
//读取密码
raf.read(bs);
String pwd=new String(bs,"utf-8").trim();
//获取昵称
raf.read(bs);
String nick=new String(bs,"utf-8").trim();
//读取年龄
int ag=raf.readInt();//读取到int类型4字节
System.out.println(name +" "+pwd+" "+nick+" "+ag);
System.out.println(raf.getFilePointer());//获取指针位置
}
raf.close();
}
}