RandomAccessFile类

RandomAccessFile类

RandomAccessFile类

1 什么是RandomAccessFile类

java.io.RandomAccessFile类能对文件的内容进行读写操作

2 为什么需要RandomAccessFile类

File类智能创建,删除文件或获得文件信息,但是不能操作文件的内容

RandomAccessFile类可以对文件的内容进行任意的读写

3 向文件中写入内容

RandomAccessFile raf=new RandomAccessFile(<指定文件路径>,<读写模式>);

实例化对象在构造方法中:

  1. 指定一个文件路径
  2. 指定读写模式
    • r:只读模式
    • rw:读写模式

write() 能够对指定文件进行内容的写入

package cn.tedu.vip.raf;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;
/**
 * java.io.RandomAccessFile
 * 专门用来读写文件数据的API,基于指针对文件进行随机读写操作
 * 读写文件非常灵活
 * @author Tedu
 *
 */
public class RAFDemo01 {

	public static void main(String[] args) throws IOException {
		/*
		 * RandomAccessFile对象的创建
		 */
		//File f=new File("./raf.dat");//dat为后缀名
		//RandomAccessFile raf=new RandomAccessFile(f,"rw");
		/*
		 * RsndomAccessFile对象的权限
		 * r:只读模式
		 * rw:读写模式
		 * 如果创建文件时使用的是读写模式
		 * 那么这个文件会被创建
		 * 如果是只读模式会发生异常
		 */
		RandomAccessFile raf=new RandomAccessFile("./raf.det","rw");
		/*
		 * 下面代码写入的内容是
		 * 00000001
		 * raf.write(int d)
		 * 功能是向指定文件中写入给定int值的
		 * 2进制的低八位数据
		 */
		raf.write(97);
		System.out.println("over");
		
		//一定要运行关闭操作
		raf.close();
	}
}
4 从文件中读取内容

read() 能够从指定文件中读取一个字节

package cn.tedu.vip.raf;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;
/**
 * 使用RAF读取一个字节的内容
 * @author Tedu
 *
 */
public class RAFDemo02 {

	public static void main(String[] args) throws IOException {
		RandomAccessFile raf=new RandomAccessFile("./raf.det","r");
		/*
		 * int read();
		 * 从文件中读取一个字节的数据
		 * 装载到int值的低八位数据上,并返回这个int值
		 * 如果没有任何内容的位置时,那么返回-1,表示文件读完了
		 * 00000000 00000000 00000000 00000001
		 */
		int d=raf.read();
		System.out.println(d);//97
		
		d=raf.read();
		System.out.println(d);//-1
		raf.close();
	}
}
5 复制文件

配合write()和read() 能够复制指定文件到新的位置

package cn.tedu.vip.raf;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;
/**
 * 使用RandomAccessFile实现文件的复制
 * @author Tedu
 *
 */
public class CopyDemo {

	public static void main(String[] args) throws IOException {
		//负责读取数据的raf
		RandomAccessFile rafRead=new RandomAccessFile("./齐晨 - 咱们结婚吧.m4a","r");
		//负责写入的raf
		RandomAccessFile rafWrite=new RandomAccessFile("./齐晨 - 咱们结婚吧_cp.m4a","rw");
		
		//声明一个字节(只使用低八位)
		long start=System.currentTimeMillis();//检验时间
		int d;
		
		while((d=rafRead.read())!=-1) {
			rafWrite.write(d);
		}
		long end=System.currentTimeMillis();//检验时间
		System.out.println("用时:"+(end-start)+"ms");
		
		rafRead.close();
		rafWrite.close();
	}
}
6 复制文件优化

void write(byte[] data)

定义一个数组,将给定的字节数组中的所有字节一次性写出提高运行效率

package cn.tedu.vip.raf;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;
/**
 * 优化文件复制
 * 创建缓存,减少读写数据的次数
 * 单字节读写是一种随机读写形式(效率低)
 * 一组字节读写是块读写形式
 * @author Tedu
 *
 */
public class CopyDemo2 {

	public static void main(String[] args) throws IOException {
		RandomAccessFile rafRead=new RandomAccessFile("./齐晨 - 咱们结婚吧.m4a","r");
	    RandomAccessFile rafWrite=new RandomAccessFile("./齐晨 - 咱们结婚吧_cp.m4a","rw");
	    /*
	     * int read(byte[] date)
	     * 一次性读取给定字节数组长度的字节量,并存到该数组中
	     * 返回实际读取到的字节量
	     * 如果返回-1表示本次读取已经到末尾(没有读取到数据)
	     * 
	     * void write(byte[]data)
	     * 将给定的字节数组中的数据写入文件中
	     * 
	     * void write(byte[] data,int offset,int len)
	     * 将给定的字节数组中的数据,从下标为offset的位置开始
	     * 一次性写入len个长度
	     */
	    
	    //定义缓存
	    byte[] data=new byte[1024*10];//10k的缓存
	    int len;//每次读取到的字节数
	    
	    long start=System.currentTimeMillis();
	    
	    while((len=rafRead.read(data))!=-1) {
	    	//将读取到的信息写入
	    	rafWrite.write(data,0,len);
	    }
	    long end=System.currentTimeMillis();
	    
	    System.out.println("用时:"+(end-start)+"ms");
	    //别忘了关闭读写
	    rafRead.close();
	    rafWrite.close();	
	}
}
7 写入文件

byte[]data=str.getBytes("utf-8");

raf.write(data)

使用byte类型数组

package cn.tedu.vip.raf;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;
/**
 * 向文件中写入文本(中文)
 * @author Tedu
 *
 */
public class WriteStringDemo {

	public static void main(String[] args) throws IOException {
		RandomAccessFile raf=new RandomAccessFile("raf.txt", "rw");
		String str="左边~跟我一起画条龙";
		/*
		 * String对象的方法
		 * byte[]getBytes();
		 * 功能是将字符串中的字符转换为字节
		 * 按照系统默认的字符集
		 * 
		 * byte[]getBytes(String csn)
		 * 功能是将字符串中的字符转换为字节
		 * 按照指定的字符集
		 */
		byte[] data=str.getBytes("utf-8");
		raf.write(data);
		System.out.println("over");
		raf.close();//一定要记得关闭,重点
	}
}
8 读取文本

byte[] data=new byte[(int)raf.length()];

raf.read(data);

提高读取效率

package cn.tedu.vip.raf;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;
/**
 * 读取文本数据
 * @author hp
 *
 */
public class ReadStringDemo {

	public static void main(String[] args) throws IOException {
		RandomAccessFile raf=new RandomAccessFile("raf.txt","r");
		
		//System.out.println(raf.length());
		
		byte[] data=new byte[(int)raf.length()];
		//读取文件中的所有数据到data数值
		raf.read(data);
		/*
		 * String类中有一个构造方法
		 * String(byte[] data,String scn)
		 * data是字节数值,会按照scn指定的字符集解析字符,并创建对象
		 */
		
		String str=new String(data,"utf-8");
		System.out.println(str);	
		
		raf.close();
	}
}
9 编写简易记事本

程序启动后要求用户输入一个文件名,然后对该文件进行读写操作,

之后用户在控制台输入的每行字符串都写入到该文件中(统一用UTF-8编码)写入文件的字符

package cn.tedu.vip.raf;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.util.Scanner;
/**
 * 简易记事本
 * 程序启动后用户输入一个文件名
 * 针对这个文件进行读写操作
 * 使用循环让用户向记事本写入字符串
 * 统一编码utf-8,不用考虑换行问题
 * 输入exit结束循环
 * @author Tedu
 *
 */
public class Note {

	public static void main(String[] args) throws IOException {
		Scanner scan=new Scanner(System.in);
		System.out.println("请输入要创建的文件名");
		String fileName=scan.nextLine();//输入一行全部读取
		RandomAccessFile raf=new RandomAccessFile(fileName, "rw");
		//循环开始记事
		while(true) {
			System.out.println("请输入记事");
			String msg=scan.nextLine();
			if(msg.equals("exit")){//如果信息退出
				//输入exit循环退出
				break;
			}
			byte[] data=msg.getBytes("utf-8");
			raf.write(data);
		}
		System.out.println("谢谢使用");
		
		raf.close();
	}
}
10 RAF中的指针及使用

seek(int pos)

定位指针的位置

package cn.tedu.vip.raf;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;
/**
 * 读写数据以及Raf指针的操作
 * @author Tedu
 *
 */
public class RafAeekDemo {

	public static void main(String[] args) throws IOException {
		RandomAccessFile raf=new RandomAccessFile("data.dat", "rw");
		//获取指针当前的位置
		long pos=raf.getFilePointer();
		System.out.println(pos);
		
		int max=Integer.MAX_VALUE;//21亿多
		/*                            vvvvvvvv
		 * 01111111 11111111 11111111 11111111 
		 */
		raf.write(max>>>24);
		System.out.println("pos:"+raf.getFilePointer());//1
		raf.write(max>>>16);
		raf.write(max>>>8);
		raf.write(max);
		System.out.println("pos:"+raf.getFilePointer());//4
		
		//直接写一个int数据
		raf.writeInt(max);
		System.out.println("pos:"+raf.getFilePointer());//8
		raf.writeLong(123);
		System.out.println("pos:"+raf.getFilePointer());//16
		raf.writeDouble(123.123);
		System.out.println("pos:"+raf.getFilePointer());//24
		
		//读取文件数据
		/*
		 * 指针移动到指定位置
		 * void seek(long pos)
		 */
		System.out.println("---------------");
		raf.seek(0);
		int data=raf.read();
		System.out.println("pos:"+raf.getFilePointer());
		System.out.println(data);
		
		raf.seek(4);
		int i=raf.readInt();
		System.out.println("pos:"+raf.getFilePointer());//8
		long I=raf.readLong();
		System.out.println("pos:"+raf.getFilePointer());//16
		double d=raf.readDouble();
		System.out.println("pos:"+raf.getFilePointer());//24
		System.out.println(i);
		System.out.println(I);
		System.out.println(d);
		
		System.out.println("over");
		
		raf.close();//切记关闭
	}
}
11 用户注册练习

程序启动后顺序输入:用户名,密码,昵称,年龄

然后将其写入文件user.dat中保存

package cn.tedu.vip.raf;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.util.Arrays;
import java.util.Scanner;
/**
 * 完成用户注册功能
 * 将一个用户信息保存到一个文件中
 * 这个文件可以保存多个用户信息
 * 程序运行一次保存一个用户
 * 用户名(String) 密码(String)昵称(String) 年龄(int)
 * 每个用户信息占用一百字节
 * 其中每个字符串信息占32字节年龄占4字节
 * @author Tedu
 *
 */
public class RegDemo {

	public static void main(String[] args) throws IOException {
		Scanner scan=new Scanner(System.in);
		System.out.println("开始注册,请输入您的信息");
		System.out.println("请输入用户名");
		String name=scan.nextLine();
		System.out.println("请输入密码");
		String pwd=scan.nextLine();
		System.out.println("请输入昵称");
		String nick=scan.nextLine();
		System.out.println("请输入年龄");
		int age=scan.nextInt();
		
		System.out.println(name+","+pwd+","+nick+","+age);
		
		RandomAccessFile raf=new RandomAccessFile("user.dat", "rw");
		//将指针移动到最后
		raf.seek(raf.length());
		//将用户名转换为字节数组
		//写用户名
		byte[] arrName=name.getBytes("utf-8");
		arrName=Arrays.copyOf(arrName, 32);//扩容让系统书写32字节
		raf.write(arrName);
		System.out.println(raf.getFilePointer());//获取指针位置
		
		//写密码
		byte[] arrPwd=pwd.getBytes("utf-8");
		arrPwd=Arrays.copyOf(arrPwd, 32);
		raf.write(arrPwd);
		System.out.println(raf.getFilePointer());
		
		//写昵称
		byte[] arrNick=nick.getBytes("utf-8");
		arrNick=Arrays.copyOf(arrNick, 32);
		raf.write(arrNick);
		System.out.println(raf.getFilePointer());
		
		//写年龄
		raf.writeInt(age);
		System.out.println(raf.getFilePointer());
		
		System.out.println("注册成功");
				
		raf.close();
	}
}
12 读取用户练习

显示user.dat文件中所有的用户信息

package cn.tedu.vip.raf;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;
/**
 * 显示user.dat中所有用户信息
 * @author Tedu
 *
 */
public class ShowAllUserDemo {

	public static void main(String[] args) throws IOException {
		RandomAccessFile raf=new RandomAccessFile("user.dat", "r");
		for(int i=0; i<raf.length()/100; i++) {
			byte[]data=new byte[32];
			//读取第一个32字节
			raf.read(data);
			String name=new String(data,"utf-8");
			System.out.println(raf.getFilePointer());//32
			
			//读取下一个32字节
			raf.read(data);
			String pwd=new String(data,"utf-8");
			System.out.println(raf.getFilePointer());//64
			
			//读取下一个32字节
			raf.read(data);
			String nick=new String(data,"utf-8");
			System.out.println(raf.getFilePointer());//96
			
			//读取最后4字节
			int age=raf.readInt();
			System.out.println(raf.getFilePointer());//100
			//raf.read(data);
			//String age=new String(data,"uft-8");
			//System.out.println(raf.getFilePointer());
			System.out.println(name.trim()+","+pwd.trim()+","+nick.trim()+","+age);
		}
		System.out.println("over");
		raf.close();
	}
}
13 修改用户练习

程序启动后要求用户输入用户名和新昵称,然后将user.dat文件中对应的记录进行修改,如果输入的用户名在user.dat文件中不存在,则输出:查无此人

package cn.tedu.vip.raf;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.util.Arrays;
import java.util.Scanner;
/**
 * 修改昵称
 * 程序运行后输入用户名和新昵称
 * 在user.dat中查找对应用户
 * 如果存在修改昵称为新昵称
 * 如果不存在输出查无此人
 * @author Tedu
 *
 */
public class UpdateDemo {

	public static void main(String[] args) throws IOException {
		Scanner scan=new Scanner(System.in);
		System.out.println("请输入用户名");
		String name=scan.nextLine();
		System.out.println("请输入新昵称");
		String nick=scan.nextLine();

		RandomAccessFile raf=new RandomAccessFile("user.dat", "rw");
		boolean isUpdated=false;//表示是否修改的变量,默认没修改
		for(int i=0; i<raf.length()/100; i++) {
			//移动指针至本次循环对应用户的起始位置
			raf.seek(i*100);
			//读取用户名
			byte[]data=new byte[32];
			raf.read(data);
			String n=new String(data,"utf-8").trim();
			//对比当前取出的用户名和用户要修改的用户名是否相同
			if(n.equals(name)) {
				//移动到昵称位置
				raf.seek(i*100+64);
				data=nick.getBytes("utf-8");
				data=Arrays.copyOf(data, 32);
				raf.write(data);
				isUpdated=true;
				System.out.println("修改成功");
				break;	
			}
		}//for循环结束
		//判断是否修改过
		if(!isUpdated) {
			System.out.println("查无此人");
		}
		raf.close();
	}
}

I(Input)\O(Output)

1 什么是IO

IO:Input,Output java标准的输入与输出

javaIO是以标准的操作对外界设备进行数据交换并将读写分为输入与输出

IO是顺序读写方式,只能顺序向后进行读或读写操作,并且不能同时进行读和写操作

2 为什么需要IO

功能上与RandomAccessFile一样,但是RAF是随机读写形式,而文件流是顺序读写形式,对于读写的灵活而言不如RAF,但是基于流连接可以完成复杂数据的读写

3 IO的分类

按方向分:输入流和输出流

java.io.InputStream:所有字节输入流的超类

规定了读取字节的相关方法

java.io.OututStream: 所有字节输出流的超类

规定了写出字节的相关方法

按使用方式:节点流与处理流,也称为低级流和高级流

节点流:真实连接数据源与程序之间的“管道”,负责实际搬运数据的流,流读写一定是建立在节点流的基础上进行的

处理流:不能独立存在,必须连接在其他流上,使得在读写数据的过程中,当数据流经当前处理流时,对其做某些加工处理,简化对数据的相关操作

4 文件流的使用

write(byte[] data)

向文件中写入信息、读取信息

package cn.tedu.vip.io;

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
/**
 * 文件流写操作
 * @author Tedu
 *
 */
public class FosDemo {

	public static void main(String[] args) throws IOException {
		/*
		 * 创建文件流的方法
		 * FileOutputStream(File file)
		 * FileOutputStream(String path)
		 * 上面两种创建形式都是覆盖输出模式
		 * 如果当前文件中有内容会全部清除重新写
		 * 
		 * FileOutputStream(File file,true)
		 * FileOutputStream(String path,true)
		 * 追加模式
		 * 在源文件所有内容最后在追加输出的内容
		 * 不会清除源文件的内容
		 */
		FileOutputStream fos=new FileOutputStream("fos.txt",true);//加true追加
		
		String str="流太厉害了~奥利给!";
		//String str="文件输出流~奥利给!";
		
		byte[] data=str.getBytes("gbk");
		
		fos.write(data);
		System.out.println("over");
		fos.close();
	}
}
package cn.tedu.vip.io;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
/**
 * 使用文件输入流读取文件中的内容
 * @author Tedu
 *
 */
public class FisDemo {

	public static void main(String[] args) throws IOException {
		FileInputStream fis=new FileInputStream("fos.txt");
		/*
		 * fis对象是按顺序读取文件中的内容
		 * int read();
		 * 从头读取文件中的内容,再次调用获得下一个字节的内容
		 * 如果读取到末尾返回-1
		 * 
		 * int read(byte[] data)
		 * 从头读取数据,将读取到的内容存放到data中
		 * 如果读取到数据,返回读取到数据的字节数
		 * 如果没读取到数据,返回-1
		 * 再次调用从最后读取到的数据后面继续读取
		 */
		//int data;
		//while((data=fis.read())!=-1) {
			//System.out.println(data);
		//}
		byte[] data=new byte[1024];
		int len=fis.read(data);
		System.out.println("读取到了:"+len+"字节的内容");
		
		String str=new String(data,0,len,"GBK");
		System.out.println(str);
		
		 /*int n=fis.read();
		 System.out.println(n);
		 
		 n=fis.read();
		 System.out.println(n);*/
		
		fis.close();
	}
}
posted @ 2021-03-12 22:44  指尖上的未来  阅读(255)  评论(0)    收藏  举报