Java中的文件数据读写API-RAF

java.io.RandomAccessFile

RAF是专门用来读写文件数据的API,其基于指针对文件任意位置进行读写
重点是最后面的字符串的写入与读出

一、对文件操作需要创建对象

RandomAccessFile raf = new RandomAccessFile("./raf.dat",“rw”);

  1. 创建实例对象时,需要:

​ 导包:import java.io.RandomAccessFile;
​ 抛出异常: throws FileNotFoundException(抛出的异常也会导包 import java.io.FileNotFoundException;)

  1. 传入参数为:

​ 路径:可以是字符串也可以是File对象
​ 操作名(字符串类型):r(只读,访问文件需存在),rw(读写,访问文件不存在会自动创建)

import java.io.FileNotFoundException;
import java.io.RandomAccessFile;
public class RafDemo1 {
	public static void main(String[] args) throws FileNotFoundException {
		/*
		 * 对当前目录下的raf.dat文件读写数据
		 */
		//创建实例对象(需要导包和抛出异常)
		//传入参数为 路径(可以是字符串也可以是File对象)
		RandomAccessFile raf = new RandomAccessFile("./raf.dat","rw");
	}
}

二、对文件的写入操作

write()
需要抛出异常,需要传入写入的数据,写入的结果是该数据对应的二进制值

注意:写入的值是给的值的二进制的最低的那八位二进制

import java.io.IOException;
import java.io.RandomAccessFile;
public class RafDemo1 {
	public static void main(String[] args) throws IOException{
		RandomAccessFile raf = new RandomAccessFile("./raf.dat","rw");
		
		//对文件的写入操作
		//需要抛出异常,需要传入写入的数据,写入的结果是该数据对应的二进制值
		raf.write(97);  
		System.out.println("写入完毕!");
		raf.close(); //用完了要关闭
	}
}

三、对文件的读出操作

int read()
从文件中读取1个字节,并以int形式返回,若返回值为-1,则表示文件末尾

调用一次读入一个字节,再次调用会读入下一个字节

import java.io.IOException;
import java.io.RandomAccessFile;
public class RafDemo2 {
	public static void main(String[] args) throws IOException {
		RandomAccessFile raf = new RandomAccessFile("./raf.dat","r");
		int d = raf.read();
		System.out.println(d);
	}
}

四、对文件进行复制

上述方法的综合应用

通过对文件的读和写来达到文件的复制

该方法不建议,因为被硬盘读取的短板限制了复制的效率

import java.io.IOException;
import java.io.RandomAccessFile;
public class CopyDemo {
	public static void main(String[] args) throws IOException, InterruptedException {
		RandomAccessFile src = new RandomAccessFile("./image.jpg","r");
		RandomAccessFile desc = new RandomAccessFile("./image_cp.jpg","rw");
		int d = -1;
		//记录时间,查看效率
		//开始时间
		long start = System.currentTimeMillis();
		//循环条件中读取源文件的每个字节,当读取的值为-1时,读取完毕
		//循环体重将读取的每个字节写入到复制文件中
		while((d=src.read()) != -1){
			desc.write(d);
		}
		//结束时间
		long end = System.currentTimeMillis();
		System.out.println("复制完毕,耗时:"+(end-start)/1000+"秒");
		//注意:一定不要忘了关闭文件
		src.close();
		desc.close();
	}
}

五、高效文件复制

单字节读写:是随机读写,效率差

块读写:是一组一组字节的读写,效率高
块读写通过提高每次读写的数据量,减少读写次数,可以提高效率

read和write方法的重载方法:

  1. int read(byte[] data)
    一次性从文件中读取给定数组总长度的字节量,并将读取到的数据存入该数组中
    返回值为实际读取到的字节量
    若返回值为-1,则表示读取的为文件末尾(本次没有读取到任何数据)
  2. void write(byte[] data)
    一次性将给定字节数组中所有的数据写入文件
    但是要注意,这样的话最后一次若没有读满,将会多写一段倒数第二段的数据
    我们要读多少,写多少,针对这种情况
    write还有个重载的方法
  3. void write(byte[] data,int start,int len)
    将给定字节数组从下标start处开始连续读写len(读取数据的长度)个字节,再一次性写入文件
import java.io.IOException;
import java.io.RandomAccessFile;
public class CopyDemo2 {
	public static void main(String[] args) throws IOException {
		RandomAccessFile src = new RandomAccessFile("./image.jpg","r");
		RandomAccessFile desc = new RandomAccessFile("./image_copy.jpg","rw");
		long start = System.currentTimeMillis(); //开始复制时间
		//每次读取10k数据,10k左右是效果最好的读取效率
		byte[] data = new byte[1024*10]; //定义每次读多少字节的数组
		int len = -1; //记录每次实际读取的字节数
		while((len = src.read(data)) != -1){
			desc.write(data, 0, len);
		}
		long end = System.currentTimeMillis(); //结束复制时间
		System.out.println("复制完毕,耗时:"+(end-start)/1000+"秒");
		//注意:一定不要忘了关闭文件
		src.close();
		desc.close();
	}
}

六、基本类型与字符串的读写操作

字符串部分

使用RAF向文件中写入字符串

String 提供了转换为字节的方法
byte[] getBytes(“字符集格式”);
将当前字符串按照给定字符集转换为一组字节
传入的参数为字符集名称,不区分大小写,如果不写,按照系统默认的字符集操作
推荐用传参的,不要按照系统默认的,因为系统不同将会不能运行

import java.io.IOException;
import java.io.RandomAccessFile;
import java.util.Scanner;
public class WriteStringDemo {
	public static void main(String[] args) throws IOException {
		RandomAccessFile raf = new RandomAccessFile("./raf.txt", "rw");
		Scanner input = new Scanner(System.in);
		System.out.println("请输入要写入文件的字符串:");
		String line = input.nextLine();
		byte[] data = line.getBytes("utf-8");//将字符串转换为字节数组
		raf.write(data);
        //追加一句
		System.out.println("请再输入后面的话:");
		raf.write(input.nextLine().getBytes("utf-8"));
		System.out.println("写入完毕!");
		raf.close();
		input.close();
	}
}
使用RAF读取文本数据,将文本数据转换为字符串输出
import java.io.IOException;
import java.io.RandomAccessFile;
public class ReadStringDemo {
	public static void main(String[] args) throws IOException {
		RandomAccessFile src = new RandomAccessFile("./raf.txt", "r");
		//创建一个接收读取数据的字节数组
		//该数组长度是文件长度,返回值是long需要强转为int
		byte[] data = new byte[(int)src.length()];
		src.read(data);
		//字符串类有一个有参构造方法,传入字节数组,并定义编码格式
		String str = new String(data,"utf-8");
		System.out.println(str);
		src.close();
	}
}

基本数据类型

读写基本类型数据以及RAF基于指针的操作
写入操作:

操作原理
一个int型为4字节
int的最大值在二进制中表示为
01111111 11111111 11111111 11111111
write写入每次只能写入低八位,我们可以通过逻辑右移位>>>来获取每个八位的值

针对这种情况,java根据该原理,提供了方法
writeInt(int i); 将给定int值对应的4个字节一次性写入
其他基本类型相同

指针操作:

获取指针位置 getFilePointer();

我们写入操作结束后,指针指向了文件末尾,继续读取会为-1
所以在进行读取操作前,我们需要修改指针位置

我们可以用 seek() 方法将指针拨回0位置

seek方法: void seek(long pos)
移动指针到指定位置

读出操作:

操作原理与写入相同,读出操作也有对应的一次性读出的方法
例如:int型用readInt()

import java.io.IOException;
import java.io.RandomAccessFile;
public class RafDemo3 {
	public static void main(String[] args) throws IOException {
		RandomAccessFile raf = new RandomAccessFile("./raf.dat", "rw");
		//向文件写入一个int最大值(4字节)
		//01111111 11111111 11111111 11111111
		int max = Integer.MAX_VALUE;
		//由于read只能读取低八位的值
		//通过逻辑右移位>>>,来获取每个八位的值
//		for(int i = 24;i>=0;i-=8){
//			raf.write(max>>>i);
//		}
		//java提供了一次写入的方法,该方法原理就是上述方法
		//写入其他基本类型的方法大致相同
		raf.writeInt(max); //写入int最大值 
		raf.writeInt(128); //写入int值128
		raf.writeLong(1); //写入long类型
		System.out.println("写入完毕");
		//获取指针位置getFilePointer()
		System.out.println("此时指针位置:"+raf.getFilePointer());
		//进行读取操作前,我们需要修改指针位置
		//注意这里文件指针已经指向了末尾,继续读取会为-1
        //将抛出异常EOFException,EOF(end of file)文件末尾
		raf.seek(0); //指针指向第一个数字的起始位置
		int d = raf.readInt();
		System.out.println("读出写入的值1:"+d);
		raf.seek(4);  //指针指向第二个数字的起始位置
		System.out.println("读出写入的值2:"+raf.readInt());
		raf.seek(8);  //指针指向第三个数字写入的位置
		System.out.println("读出写入的值3:"+raf.readLong());
		
		//通过指针对文件修改
		//将第二个int值改为int最小值
		raf.seek(4);
		raf.writeInt(Integer.MIN_VALUE);
		raf.seek(4);
		System.out.println("输出修改后的值"+raf.readInt());
		raf.close();
	}
}

练习:用户信息的注册、显示与修改

用户注册,信息写入
package raf;

import java.io.IOException;
import java.io.RandomAccessFile;
import java.util.Arrays;
import java.util.Scanner;

/**
 * 用户注册
 * 程序启动后,要求用户输入注册信息(用户名、密码、昵称、年龄)
 * 其中除了年龄是int,其余三个皆为String
 * 然后将该信息写入user.dat文件中保存
 * 
 * 我们对其做限制
 * 每条用户信息占100字节
 * 用户名、密码、昵称各占32字节,年龄占4字节
 * @author Tian
 *
 */
public class RegDemo {
	public static void main(String[] args) throws IOException {
		System.out.println("欢迎注册");
		RandomAccessFile raf = new RandomAccessFile("./user.dat", "rw");
		//每次运行代码时,将指针移动到文件末尾,以便再次追加数据
		raf.seek(raf.length());
		String name;
		String pwd;
		String nick;
		int age;
		Scanner input = new Scanner(System.in);
		System.out.print("请输入用户名:");
		name = input.nextLine();
		System.out.print("请输入密码:");
		pwd = input.nextLine();
		System.out.print("请输入昵称:");
		nick = input.nextLine();
		System.out.print("请输入年龄:");
		age = Integer.parseInt(input.nextLine());
		System.out.println("该用户信息为:用户名("+name+"),密码("+pwd+"),昵称("+nick+"),年龄("+age+")");

		//写入用户名
		byte[] data = name.getBytes("utf-8");
		//数组扩容为32字节
		data = Arrays.copyOf(data, 32);
		raf.write(data);

		//写入密码
		raf.write(Arrays.copyOf(pwd.getBytes("utf-8"), 32));
		//写入昵称
		raf.write(Arrays.copyOf(nick.getBytes("utf-8"), 32));
		//写入年龄
		raf.writeInt(age);
		System.out.println("写入完毕!");
	}
}
用户信息显示
package raf;

import java.io.IOException;
import java.io.RandomAccessFile;

/**
 * 将user.dat文件中的用户信息显示到控制台
 * @author Tian
 *
 */
public class ShowAllUserDemo {
	public static void main(String[] args) throws IOException {
		RandomAccessFile raf = new RandomAccessFile("./user.dat","r");
		//定义读取字符串的字节数组
		byte[] data = new byte[32];
		for(int i=0;i<raf.length()/100;i++){
			//读取用户名
			raf.read(data);
			String name = new String(data,"utf-8").trim(); //注意要加trim去除两端空格
			//读取密码
			raf.read(data);
			String pwd = new String(data,"utf-8").trim(); //注意要加trim去除两端空格
			//读取昵称
			raf.read(data);
			String nick = new String(data,"utf-8").trim(); //注意要加trim去除两端空格
			//读取年龄
			int age = raf.readInt();
			//输出读取信息
			System.out.println("用户"+(i+1)+"信息为:用户名("+name+"),密码("+pwd+"),昵称("+nick+"),年龄("+age+")");
		}
		raf.close();
	}
}
用户信息修改
package raf;

import java.io.IOException;
import java.io.RandomAccessFile;
import java.util.Arrays;
import java.util.Scanner;

/**
 * 完成修改昵称的操作
 * 程序启动后,要求输入用户名和新的昵称,
 * 然后修改user.dat文件中该用户的昵称
 * 若输入的用户名在user.dat文件中不存在
 * 提示信息:该用户不存在!
 * @author Tian
 *
 */
public class UpdataDemo {
	public static void main(String[] args) throws IOException {
		Scanner input = new Scanner(System.in);
		System.out.print("请输入要修改用户的用户名:");
		String name = input.nextLine();
		System.out.print("请输入要修改的昵称:");
		String nick = input.nextLine();
		//用户输入结束后再打开文件
		RandomAccessFile raf = new RandomAccessFile("./user.dat", "rw");
		for(int i=0;i<raf.length();i+=100){
			//遍历获取用户名
			//指针拨到用户名所在指针
			raf.seek(i);
			//定义读取文件信息的字节数组
			byte[] data = new byte[32];
			//获取文件中的用户名,注意去除空格
			raf.read(data);
			String uname = new String(data,"utf-8").trim();
			//查找有没有用户名与输入的用户名相同
			if(name.equals(uname)){
				//如果有相同的用户名,提示用户输入修改的昵称
				//但是由于文件这时已经打开了,在做服务端的时候不要这样做
				//等待用户输入,会一直占用文件,在服务端,其他人就不能访问这个文件了
				//所以我们先把数据都让用户输入,再打开文件运行
				//System.out.print("请输入要修改的昵称:");
				//String nick = input.nextLine();
				//将该昵称写入到当前用户的昵称中,覆盖以前的昵称
				//指针拨到i+64的位置
				raf.seek(i+64);
				//进行写入操作
				raf.write(Arrays.copyOf(nick.getBytes("utf-8"), 32));
				System.out.println("修改成功!");
				raf.close();
				input.close();
				return;
			}
		}
		System.out.println("查无此人!");
		raf.close();
		input.close();
	}
}
  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Java提供了多种方式来读写和查询txt文件。以下是一些常见的方法: 1. 使用File类:可以使用File类来创建、删除、重命名、复制和移动txt文件。可以使用FileReader和FileWriter类来读写文件内容。 ```java // 读取文件内容 try (BufferedReader br = new BufferedReader(new FileReader("file.txt"))) { String line; while ((line = br.readLine()) != null) { System.out.println(line); } } catch (IOException e) { e.printStackTrace(); } // 写入文件内容 try (BufferedWriter bw = new BufferedWriter(new FileWriter("file.txt"))) { bw.write("Hello, World!"); } catch (IOException e) { e.printStackTrace(); } ``` 2. 使用Scanner类:可以使用Scanner类来读取txt文件的内容。Scanner类提供了方便的方法来读取文件的各种数据类型。 ```java try (Scanner scanner = new Scanner(new File("file.txt"))) { while (scanner.hasNextLine()) { String line = scanner.nextLine(); System.out.println(line); } } catch (FileNotFoundException e) { e.printStackTrace(); } ``` 3. 使用RandomAccessFile类:RandomAccessFile类提供了对文件的随机访问,可以根据需要在文件定位、读取和写入数据。 ```java try (RandomAccessFile raf = new RandomAccessFile("file.txt", "rw")) { // 读取文件内容 String line; while ((line = raf.readLine()) != null) { System.out.println(line); } // 写入文件内容 raf.writeBytes("Hello, World!"); } catch (IOException e) { e.printStackTrace(); } ``` 4. 使用第三方库:除了使用Java原生的类,还可以使用第三方库来简化文件操作。例如,使用Apache Commons IO库可以更方便地读写文件。 ```java // 读取文件内容 try { List<String> lines = FileUtils.readLines(new File("file.txt"), "UTF-8"); for (String line : lines) { System.out.println(line); } } catch (IOException e) { e.printStackTrace(); } // 写入文件内容 try { FileUtils.write(new File("file.txt"), "Hello, World!", "UTF-8"); } catch (IOException e) { e.printStackTrace(); } ``` 以上是一些常见的方法,可以根据具体需求选择适合的方式来读写和查询txt文件

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值