开头:RAF的简单介绍
package raf;
import java.io.RandomAccessFile;
/**
* java.io.RandomAccessFile
* RAF是专门用来读写文件数据的API.其基于指针对文件数据进行读写
* 操作,可以灵活的编译文件数据内容。
* 创建RAF时可以指定对该文件的权限,常用的有两种:
* r:只读模式
* rw:读写模式
* 对当前目录中的raf.dat文件读写
* RAF支持两种常用构造方法:
* RandomAccessFile(File file, String mode)
* RandomAccessFile(String path, String mode)
*
* 注:相对路径中"./"是可以忽略不写的,因为
* 默认就是从当前目录开始。
*
* RAF创建时含有写权限的情况下,当指定文件
* 不存在时会自动将其创建出来
* @author 13651
*
*/
public class RafDemo {
public static void main(String[] args) throws Throwable {
RandomAccessFile raf = new RandomAccessFile("raf.dat", "rw");
/**
* void write(int d)
* 向文件中写入1字节,写的是给定int值
* 对应2进制的“低八位”
* vvvvvvvv
* 00000000 00000000 00000000 00000001
*/
raf.write(256);
System.out.println("写出完毕!");
raf.close();
}
}
RAF读写基本类型数据,以及RAF的指针操作:
注意:RandomAccessFile read总是在指针当前位置读或写,不管是读还是写,指针都会自动往后移一下
package raf;
import java.io.RandomAccessFile;
/**
* RAF读写基本类型数据,以及RAF的指针操作
*
* @author 13651
*
*/
public class RafDemo2 {
public static void main(String[] args) throws Throwable {
RandomAccessFile raf = new RandomAccessFile("test.txt", "rw");
//写入一个int最大值到文件中
int max = Integer.MAX_VALUE;
long pos = raf.getFilePointer();
System.out.println(pos);
/**
* int最大值的2进制形式:
* vvvvvvvv
* 01111111 11111111 11111111 11111111
*/
raf.write(max>>>24);
pos = raf.getFilePointer();
System.out.println(pos);//1
raf.seek(pos);
//RandomAccessFile read总是在指针当前位置读或写,不管是读还是写,
//指针都会自动往后移一下
raf.readInt();
raf.write(max>>>16);
pos = raf.getFilePointer();
System.out.println(pos);//2
raf.write(max>>>8);
pos = raf.getFilePointer();
System.out.println(pos);//3
raf.write(max);
pos = raf.getFilePointer();
System.out.println("!!");
System.out.println(pos);//4
/*
* void writeInt(int d)
* 连续写出4个字节,将给定的int值写出。
* 等同上面4次write方法。
* void seek(position)指针的滑动,括号内为指定指针的位置
*
*/
raf.writeInt(max);
pos = raf.getFilePointer();
System.out.println(pos);//8
raf.writeLong(123L);
raf.seek(8);//读之前必须把指针移动到读取字节之前,
//不然会抛出EFOException异常
long l = raf.readLong();
System.out.println(l);
pos = raf.getFilePointer();
System.out.println(pos);//16
raf.writeDouble(123.123);
pos = raf.getFilePointer();
raf.seek(pos);//读之前必须把指针移动到读取字节之前,不然会
//抛出EFOException异常
double d = raf.readDouble();
System.out.println(d);
System.out.println(pos);//24
//运行到这,文件有24个字节,4+4+8+8
System.out.println("写入完毕!");
raf.close();
}
}
注意指针的移动语句seek()位置的影响
package day04;
import java.io.RandomAccessFile;
/**
* 创建一个"raf.dat"的文件,并在其中写出一个int的最大值,long的最大值,
* 然后将其分别读取出来并输出
* @author Admin
*
*/
public class Test01 {
public static void main(String[] args) throws Throwable {
RandomAccessFile raf = new RandomAccessFile("raf.dat", "rw");
long pos = raf.getFilePointer();
int max = Integer.MAX_VALUE;
raf.writeInt(max);
raf.seek(pos);
System.out.println(raf.readInt());
long lMax = Long.MAX_VALUE;
pos = raf.getFilePointer();//获取文件指针必须要在write之前,
//否则会Console会有EFOException异常
raf.writeLong(lMax);
raf.seek(pos);//读之前必须把指针移动到读取字节之前,
//不然会抛出EFOException异常
System.out.println(raf.readLong());
raf.close();
}
}
中间:RAF的读操作
package raf;
import java.io.RandomAccessFile;
/**
* 读取文件数据
* @author 13651
*
*/
public class ReadDemo {
public static void main(String[] args) throws Throwable {
/**
* 读取当前目录中raf.dat文件内容
*/
RandomAccessFile raf = new RandomAccessFile("raf.dat","rw");
/**
* int read()
* 读取一个字节,并以int形式返回。
* 若返回值为-1则表示读取到文件末尾。
* 八位二进制,写入-1,读出为255.
* 无论输入啥,对256取模就是结果。
*/
int d =raf.read();
System.out.println(d);
raf.close();
}
}
结尾:RAF的复制
1.高效率复制,块复制:
package raf;
import java.io.RandomAccessFile;
/**
* 若希望提高读写效率,可以通过提高每次实际读写的数据量,
* 减少实际发生的读写操作来做到。
* 单字节读写:随机读写
* 一组字节读写:块读写
* 机械硬盘(磁盘)的块读写效率还是比较好的。但是
* 随机读写效率极差。
* @author 13651
*
*/
public class CopyDemo2 {
public static void main(String[] args) throws Throwable {
RandomAccessFile src = new RandomAccessFile("momi.msi", "r");
RandomAccessFile desc = new RandomAccessFile("vmvm.msi","rw");
/*
* RAF提供的块读写操作的方法:
* int read(byte[] data)
* 一次性读取给定字节数组长度的字节
* 量并存入到该数组中。返回值为实际
* 读取到的字节量,若返回值为-1,表示
* 本次读取的是文件末尾(没读到任何字节)
*
* void write(byte[] data)
* 一次性写出给定字节数组中的所有字节
*/
//记录每次实际读取到的字节量
int len = -1;
//每次要求读取的字节量
//10kb
byte[] data = new byte[1024*10];
long starts = System.currentTimeMillis();
while((len = src.read(data))!=-1) {
desc.write(data, 0, len);
}
long end = System.currentTimeMillis();
System.out.println("复制完毕:"+(end-starts)+"ms");//复制完毕:1500ms
src.close();
desc.close();
}
}
2.一般复制(一般不用)
package raf;
import java.io.RandomAccessFile;
/**
* 复制文件
* @author 13651
*
*/
public class CopyDemo {
public static void main(String[] args) throws Throwable {
/**
* 创建两个RAF,一个用来读原文件,一个用来往复制文件中写
* 。顺序从原文件读取每个字节写到复制文件中。
*/
RandomAccessFile src = new RandomAccessFile("12.png", "r");
RandomAccessFile desc = new RandomAccessFile("22.png", "rw");
int d = -1;
while((d = src.read())!=1) {
desc.write(d);
}
System.out.println("复制完毕!");
src.close();
desc.close();
}
}
写文件与读文件:
package raf;
import java.io.RandomAccessFile;
/**
* 写文件
* @author 13651
*
*/
public class StringWriteDemo {
public static void main(String[] args) throws Throwable {
RandomAccessFile raf = new RandomAccessFile("test.txt","rw");
String line = "愉快的代码人";
/*
* String 提供了一个转换为二进制的方法
* byte[] getByte();
*/
//可以指定字符集进行转换
byte[] data = line.getBytes("UTF-8");
raf.write(data);
System.out.println("写入完毕!");
raf.close();
}
}
package raf;
import java.io.RandomAccessFile;
/**
* 读文件
* @author 13651
*
*/
public class StringReadDemo {
public static void main(String[] args) throws Throwable {
RandomAccessFile raf = new RandomAccessFile("test.txt", "r");
/*
*
*/
byte[] data = new byte[(int)raf.length()];
raf.read(data);
String read = new String(data,"UTF-8");
System.out.println(read);
raf.close();
}
}
小测试:完成用户注册系统
package raf;
import java.io.RandomAccessFile;
import java.util.Arrays;
import java.util.Scanner;
/**
* 完成用户注册系统
*
* 程序开始后,要求用户输入:
* 用户名,密码,昵称,年龄
*
* 将该记录写入到user.dat文件中。
* 其中用户名,密码,昵称为字符串。年龄为
* 一个int值。
*
* 每条记录占有100字节,其中:用户名,密码,
* 昵称为字符串,各占32字节,年龄为int占用
* 4字节。
*
* @author 13651
*
*/
public class RegDemo {
public static void main(String[] args) throws Throwable {
Scanner sc = new Scanner(System.in);
System.out.println("请输入用户名");
String name = sc.nextLine();
System.out.println("请输入密码:");
String password = sc.nextLine();
System.out.println("请输入昵称:");
String nickName = sc.nextLine();
System.out.println("年龄:");
int age = sc.nextInt();
System.out.println(name+","+password+","+nickName+","+age);
RandomAccessFile raf = new RandomAccessFile("user.dat", "rw");
//先讲指针移动到文件末尾
raf.seek(raf.length());
//1先将用户名转成对应的一组字节
byte[] data = name.getBytes("UTF-8");
//2将数组进行扩容
data = Arrays.copyOf(data,32);
//3将该字节数组一次性写入文件
raf.write(data);
//写密码
data = password.getBytes("UTF-8");
data = Arrays.copyOf(data, 32);
raf.write(data);
//写昵称
data = nickName.getBytes();
data = Arrays.copyOf(data, 32);
raf.write(data);
//写年龄
raf.writeInt(age);
System.out.println("写入完毕!");
raf.close();
sc.close();
}
}
显示用户的信息,这边需要注意
package raf;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.util.Arrays;
import java.util.Scanner;
/**
* 显示用户信息
* @author 13651
*
*/
public class ShowAllUseDemo {
public static void main(String[] args) throws IOException {
Scanner sc = new Scanner(System.in);
System.out.println("用户输入用户名:");
String name = sc.nextLine();
System.out.println("用户输入新昵称:");
String nickName = sc.nextLine();
RandomAccessFile raf = new RandomAccessFile("user.dat", "rw");
/*
* 循环显示若干个100字节
*/
boolean flag = false;
for (int i = 0; i < raf.length()/100; i++) {
byte[] data = new byte[32];
//移动指针
raf.seek(i*100);
//将32个字节读入
raf.read(data);
//将字节数组转换为字符串
String username = new String(data,"UTF-8").trim();
raf.read(data);
String password = new String(data,"UTF-8").trim();
raf.read(data);
String nickname = new String(data,"UTF-8").trim();
int age = raf.readInt();
System.out.println(username+","+password+","+nickname+","+age);
if(name.equals(username)) {
raf.seek(i*100+64);
//获取新的用户名
data = nickName.getBytes("UTF-8");//46条语句
data = Arrays.copyOf(data, 32);//为什么上面有data,
//还是需要扩容呢?因为data只是变量,第46条语句是获取新的
//用户名称,因此重新扩容
raf.write(data);
System.out.println("修改完毕!");
flag = true;
break;
}else {
continue;
}
}
if(!flag) {
System.out.println("无此用户");
}
raf.close();
}
}