java.io.RandomAccessFile用来读写文件数据的类,其基于指针对文件数据进行读写操作(二进制字节)。
RandomAccessFile创建有两种模式:
r:只读模式,只读文件数据,并不会写入内容
rw:读写模式,对文件既可以读也可以写
常见构造方法:
RandomAccessFile(String path,String mode)
RandomAccessFile(File file,String mode)
mode:r或rw
对当前目录下的raf.dat文件进行读写操作,如果是rw模式,没有的话会自动创建,文件不存在时抛出异常FileNotFoundException。
void write(int d):向文件中写入一个字节,写入的是给定int值对应2进制低八位。
00000000 00000000 00000000 00000001
public class RandomAccessFileDemo {
public static void main(String[] args) throws IOException {
RandomAccessFile raf=new RandomAccessFile("raf.dat", "rw");
raf.write(1);
System.out.println("写出完毕");
raf.close();
}
}
int read( ):从文件中读取一个字节,并以int形式返回。若返回值为-1则表示读到了文件末尾。
public class ReadDemo {
public static void main(String[] args) throws IOException {
/**从raf.dat文件中读取1个字节*/
RandomAccessFile raf=new RandomAccessFile("raf.dat", "r");
/**
* 0-255
* 00000000 00000000 00000000 00000001
* 00000000 00000000 00000000 11111111(255)
*/
int d=raf.read();
System.out.println(d);
d=raf.read();
System.out.println(d);
raf.close();
}
}
按字节复制:
public class CopyDemo {
public static void main(String[] args) throws IOException {
RandomAccessFile src=new RandomAccessFile("RandomAccessFile类.docx", "r");
RandomAccessFile desc=new RandomAccessFile("RandomAccessFile类_cp.docx", "rw");
int d=-1;
while ((d=src.read())!=-1) {
desc.write(d);
}
System.out.println("over");
src.close();
desc.close();
}
}
传统的机械硬盘由于其物理特性决定单字节读写效率差,但是块读写效率是可以保证的。所以我们通过提高每次读取的数据量,减少实际读写的次数可以提高读写效率
随机读写:通常是单字节读写模式
块读写:一次读写一组字节的模式
int read(byte[]data):一次性从文件中读取给定字节数组
void write(byte[]data):...
void write(byte[]data,int start,int len)
总长度给定的字节量,并将读取到的字节存入到该数组中。返回值为实际读取的字节量,若返回值为-1表示读到了文件末尾,本次没有读到内容。
byte:-128-127
1 b:0000 0000
1kb=1024byte
1mb=1024kb
硬盘按1000换算
public class CopyDemo2 {
public static void main(String[] args) throws IOException {
RandomAccessFile src=new RandomAccessFile("RandomAccessFile类.docx", "r");
RandomAccessFile desc=new RandomAccessFile("RandomAccessFile类_cp2.docx", "rw");
byte[]data=new byte[1024*10];
//每次实际读取的字节量
int len=-1;
while ((len=src.read(data))!=-1) {
desc.write(data,0,len);
}
System.out.println("over");
src.close();
desc.close();
}
}
写出文本数据:
String提供了将字符串转换为字符的方法:byte[ ] getBytes()
按照系统默认字符集将当前字符串转换为对应的字节,但不推荐这种方式,不利于跨平台。
byte[] getBytes(String csn); csn:charset name
按照指定的字符集转换为一组字节。
常见字符集:
GBK:国际编码,英文1个字节,中文2个字节。
UTF-8:unicode的字符集编码,英文1个字节,中文3个字节.UTF-8支持世界流行的所有文字,所以也成为了万国码,互联网最常用字符集。
ISO8859-1:一种欧洲的编码集,不支持中文。
public class WriteStringDemo {
public static void main(String[] args) throws IOException {
RandomAccessFile raf=new RandomAccessFile("raf.txt", "rw");
String str="在";
byte[]data=str.getBytes("utf-8");
raf.write(data);
str="吗?";
data=str.getBytes("utf-8");
raf.write(data);
System.out.println("finished");
raf.close();
}
}
读取文本数据:
public class ReadStringDemo {
public static void main(String[] args) throws IOException {
/**一次性读取文件中所有数据*/
RandomAccessFile raf=new RandomAccessFile("raf.txt", "r");
byte[]data=new byte[(int)raf.length()];
raf.read(data);
/**字符串支持构造方法,将字节转换为字符串
* String(byte[]data):
* 按照系统默认字符集转换为字符串
* String(byte[]data,String csn):
* 按照指定的字符集将字节转换为对应字符串 */
String string=new String(data, "utf-8");
System.out.println(string);
raf.close();
}
}
简易记事本工具:程序启动后,要求用户输入一个文件名,然后开始对文件进行写操作之后要求用户输入的每行字符串都写入到该文件中,当用户输入了单词"exit"时,程序退出。
public class Note {
public static void main(String[] args) throws IOException {
Scanner scanner=new Scanner(System.in);
System.out.println("输入一个文件名:");
String fileName=scanner.nextLine();
RandomAccessFile raf=new RandomAccessFile(fileName, "rw");
String content="";
while (true) {
System.out.println("请输入内容:");
content=scanner.nextLine();
if (content.equals("exit")) {
break;
}
byte[]data=content.getBytes();
raf.write(data);
System.out.println();
}
System.out.println("输入结束");
scanner.close();
raf.close();
}
}
读写基本数据以及RAF如何基于指针进行读写操作:
public class Demo2 {
public static void main(String[] args) throws IOException {
RandomAccessFile raf=new RandomAccessFile("raf4.txt","rw");
/** long getFilePointer()用于获取指针位置 */
long pos=raf.getFilePointer();
System.out.println(pos);//0
int max=Integer.MAX_VALUE;
raf.write(max>>>24);
System.out.println(raf.getFilePointer());//1
raf.write(max>>>16);
System.out.println(raf.getFilePointer());//2
raf.write(max>>>8);
System.out.println(raf.getFilePointer());//3
raf.write(max);
System.out.println(raf.getFilePointer());//4
/**
* void writeInt(Int d)
* 一次性写出4字节,将给定的int值写出
*/
raf.writeInt(max);
System.out.println(raf.getFilePointer());//8
raf.writeDouble(123.23);
System.out.println(raf.getFilePointer());//16
raf.writeLong(123L);
System.out.println(raf.getFilePointer());//24
System.out.println("finished");
System.out.println(raf.read());//-1
/**
* void seek(long pos):将指针移动到指定位置
* int readInt():连续读4个字节,并返回int值,若
* 读取的过程中发现读取到文件末尾,则直接抛出文件
* 末尾的异常:EOFException
* double readDouble()
*/
raf.seek(0);
System.out.println(raf.getFilePointer());//0
System.out.println(raf.readInt());//2147483647
System.out.println(raf.getFilePointer());//4
//移动指针到double第一个字节位置,读取double值
raf.seek(8);
System.out.println(raf.readDouble());//123.23
System.out.println(raf.readLong());//123
System.out.println(raf.getFilePointer());//24
//先移动指针后修改值
raf.seek(8);
raf.writeDouble(567.567);
raf.seek(8);
System.out.println(raf.readDouble());
raf.seek(16);
System.out.println(raf.readLong());
System.out.println(raf.read());
raf.close();
}
}