JavaSE01_Day03(下)-记事本案例、RAF文件指针操作

对于同学们的疑惑总结:

1.对于Java计算机专家制定的标准不要质疑。

2.上课的时候不好意思说哪里不懂,下课的时候进行提问,这样不太好,最好课上把问题都解决了,省得课下再抽时间。

3.针对于自己不理解的内容,包老师反复讲解的内容,一定要摒弃掉自己当前不正确的思维路线,学习包老师正确的思路。

4.预习非常重要,希望大家睡觉前用手机听听课(听声音都可以)

5.笔记要下载,课后要读。

 

一、记事本案例

业务需求:

简单的记事本案例

  1. 程序启动在控制台输入一个文件名

  2. 针对这个文件进行读写操作

  3. 使用循环让用户向记事本中写入字符串

  4. 编码格式选择自己工具中使用的编码(不需要和我一致,和自己软件的编码方式一样)

  5. 不考虑换行问题,当用户在控制台中输入”exit“表示结束

代码:

 package cn.tedu;
 
 import java.io.RandomAccessFile;
 import java.util.Scanner;
 
 /**
  * 简单的记事本案例
  *1.程序启动在控制台输入一个文件名
  *2.针对这个文件进行读写操作
  *3.使用循环让用户向记事本中写入字符串
  *4.编码格式选择自己工具中使用的编码(不需要和我一致)
  *5.不考虑换行问题,当用户在控制台中输入”exit“表示结束
  * @author cjn
  *
  */
 public class RAF_Note {
 
  public static void main(String[] args) throws Exception {
  Scanner scan = new Scanner(System.in);
  System.out.println("请输入一个文件名称:");
  String fileName = scan.nextLine();
         //对文件进行读写操作
  RandomAccessFile raf = new RandomAccessFile(fileName, "rw");
  System.out.println("请输入内容,单独输入exit退出:");
  //支持用户多次输入记录的内容
  while (true) {
             //接收用户输入信息
  String message = scan.nextLine();
  //加一个终止判断,并且防止把终止的信息也写到文件中
  if ("exit".equalsIgnoreCase(message)) {
  //结束循环,不让用户继续在文件中写内容
  break;
  }
             //字符串转换为字节数组,此处注意字符集的编码格式,与自己的软件一致,否则乱码
  byte[] data = message.getBytes("utf-8");
             //向文件中写出数据
  raf.write(data);
  }
  System.out.println("写出完毕!");
  //关闭资源
         //Scanner底层是流(public Scanner(InputStream source)
         //public final static InputStream in = null;
         //用完需要关闭资源
  scan.close();
  raf.close();
  }
 }

控制台内容:

 请输入一个文件名称:
 notebook.txt
 请输入内容,单独输入exit退出:
 2021.06.17 星期四
 今天上课要认真听讲哦!
 多练代码,
 加深理解!
 exit
 写出完毕!

notebook.txt输出结果:

2021.06.17 星期四今天上课要认真听讲哦!多练代码,加深理解!

 

二、RAF文件指针操作(了解)

2.1 API方法

      (1)getFilePointer()方法:RandomAccessFile的读写操作都是基于指针的,提供了一个可以获取当前指针位置的方法,可以在指针当前所指向的位置进行读写操作。 RandomAccessFile在创建时默认指向文件开始(第一个字节),通过getFilePointer方法获取指针位置时值是"0"。此处可以当做数组下标理解,但是含义不一样。

 long getFilePointer()

      (2)seek()方法 :RandomAccessFile的提供了一个方法用于移动指针位置,使用该方法可以移动指针到指定位置。

 void seek(long pos)

2.2 RAF文件指针操作案例

 package cn.tedu;
 
 import java.io.RandomAccessFile;
 
 /**
   * 使用RAF基于指针的方式进行对基本类型数据进行读写操作
  * @author cjn
  *
  */
 public class RandomAccessFileDemo {
 
  public static void main(String[] args) throws Exception {
  //对指定文件pointer.txt进行读写操作
  RandomAccessFile raf = new RandomAccessFile("pointer.txt","rw");
  System.out.println("当前指针位置:"+raf.getFilePointer());//0
 
  //向pointer.txt文件中写出整数的最大值
  int imax = Integer.MAX_VALUE;
 
  /*由于write只能每次写入一个字节,即只能写入所读数据的低八位,要读取整个数据,需要指针移位
   *                           vvvvvvvv  
   * 01111111 11111111 11111111 11111111 整数的最大值
   * --->
   * 00000000 00000000 00000000 01111111 右移动24位
   * 00000000 00000000 01111111 11111111 右移动16位
   * 00000000 01111111 11111111 11111111 右移动8位
   * 01111111 11111111 11111111 11111111 右移动0位,低八位
  */
  //>>>表示右移运算符
  raf.write(imax>>>24);
  System.out.println("当前指针位置:"+raf.getFilePointer());//1
  raf.write(imax>>>16);
  System.out.println("当前指针位置:"+raf.getFilePointer());//2
  raf.write(imax>>>8);
  System.out.println("当前指针位置:"+raf.getFilePointer());//3
  raf.write(imax>>>0);
  System.out.println("当前指针位置:"+raf.getFilePointer());//4
 
  //简便方案: writeInt,一次写入整型数据,其它数据类型类似
  raf.writeInt(imax);
  System.out.println("当前指针位置:"+raf.getFilePointer());//8
  raf.writeDouble(Double.MAX_VALUE);//double类型数据的最大值
  System.out.println("当前指针位置:"+raf.getFilePointer());//16
  raf.writeLong(Long.MAX_VALUE);//long类型数据的最大值
  System.out.println("当前指针位置:"+raf.getFilePointer());//24
 
  //读取当前指针位置的内容
  int d = raf.read();//每次读取一个字节,低八位
  System.out.println(d);//-1,因为当前指针位于24,后面没有内容,所以读到末尾,返回-1
 
  //指定指针位置读取内容
  raf.seek(16);
  long l = raf.readLong();//从当前指针位置的下一个字节开始读取,读取一个long类型数据
  System.out.println(l);//9223372036854775807
  System.out.println("当前指针位置:"+raf.getFilePointer());//24
 
  //修改double数据类型的值
  raf.seek(8);//从当前指针位置的下一个字节开始修改数据
  raf.writeDouble(3.14);
  System.out.println("当前指针位置:"+raf.getFilePointer());//16
 
  //读取修改的double数据类型的值
  raf.seek(8);//从当前指针位置的下一个字节开始读取数据
  double dou = raf.readDouble();
  System.out.println(dou);
  System.out.println("当前指针位置:"+raf.getFilePointer());//16
 
  //关闭资源
  raf.close();
  }
 
 }

指针位置示意图如下:

测试结果:

 当前指针位置:0
 当前指针位置:1
 当前指针位置:2
 当前指针位置:3
 当前指针位置:4
 当前指针位置:8
 当前指针位置:16
 当前指针位置:24
 -1
 9223372036854775807
 当前指针位置:24
 当前指针位置:16
 3.14
 当前指针位置:16

:有关于二进制的内容,在第五阶段的附加课,附加课是大家花钱报名以后赠送的课程,直播课不讲,自己看视频学习,现在不需要去学习二进制的知识,等四个阶段都学习完以后再学二进制。

 

2.3 RAF实现用户的注册和查询

1.注册业务需求

  1. 需要用户启动程序以后,在控制台输入用户的信息,然后将信息存储到文件中。

  1. 在文件中可以不单单只去存储一个用户的信息,而是可以不断的进行存储用户信息。

  1. 用户信息的组成:用户名(String)、昵称(String)、密码(String)、年龄(int)

  1. 每位用户在存储信息时占用字节的大小为100字节(32+32+32+4=100)

  1. 用户名、昵称、密码分别占用32字节进行存储,年龄占用4字节进行存储

 package cn.tedu;
 
 import java.io.RandomAccessFile;
 import java.util.Arrays;
 import java.util.Scanner;
 
 /**
  * 注册用户信息案例
  *1.需要用户启动程序以后,在控制台输入用户的信息,然后将信息存储到文件中
  *2.在文件中可以不单单只去存储一个用户的信息,而是可以不断的进行存储用户信息
  *3.用户信息的组成:用户名(String)、昵称(String)、密码(String)、年龄(int)
  *4.每位用户在存储信息时占用字节的大小为100字节(32+32+32+4=100)
  *5.用户名、昵称、密码分别占用32字节进行存储,年龄占用4字节进行存储
  * @author cjn
  *
  */
 public class RegUserDemo {
 
  public static void main(String[] args) throws Exception {
  //1.获取用户输入的信息内容
  Scanner sc = new Scanner(System.in);
  //引导用户输入
  System.out.println("请您输入需要注册的用户信息:");
  System.out.println("请输入用户名:");
  String userName = sc.nextLine();
  System.out.println("请输入昵称:");
  String nickName = sc.nextLine();
  System.out.println("请输入密码:");
  String password = sc.nextLine();
  System.out.println("请输入年龄:");
  int age = sc.nextInt();
  //在控制台查看用户的注册信息
  System.out.println("用户名:"+userName+",昵称:"+nickName+",密码:"+password+",年龄:"+age);
 
  //2.创建文件对象,对文件进行读写操作
  RandomAccessFile raf = new RandomAccessFile("user.txt","rw");
 
  //3.将用户需要注册的信息存储到user.txt文件中,每个信息占用规定的字节
  //严谨性操作:后注册的用户不能覆盖之前注册的用户,移动到文件的末尾位置
  raf.seek(raf.length());//每次读取到文件指针的最后位置,可重复存储用户信息
 
  //4-5
  //对用户名进行写出
  byte[] arrayName = userName.getBytes("gbk");//字符串转换为字节
  arrayName = Arrays.copyOf(arrayName, 32);//数组扩容到指定大小
  raf.write(arrayName);
  //对昵称进行写出
  byte[] arrayNick = nickName.getBytes("gbk");
  arrayNick = Arrays.copyOf(arrayNick, 32);
  raf.write(arrayNick);
  //对密码进行写出
  byte[] arrayPassword = password.getBytes("gbk");
  arrayPassword = Arrays.copyOf(arrayPassword, 32);
  raf.write(arrayPassword);
  //对年龄进行写出
  raf.writeInt(age);//直接写出整个整数,4个字节
 
  //关闭资源
  sc.close();
  raf.close();
  }
 
 }

输出结果:年龄不能正常显示,乱码

 小红 xiaohong 111111  小黄 xiaohaung 222222  小蓝 xiaolan 333333  

 

2.查询业务需求

1.首先需要读取用户信息的时候,一定要按照完整用户所占的字节进行读取100字节的整数倍

第一个用户信息从0开始 第二个用户信息从100开始

2.根据上面分析可以根据当前文件的字节大小/100获取文件中存储用户的个数

3.可以根据用户不同信息所占的字节进行读取信息

 package cn.tedu;
 
 import java.io.FileNotFoundException;
 import java.io.RandomAccessFile;
 
 /**
  *查询业务需求案例:用于显示user.txt文件中的用户信息内容
  *1.首先需要读取用户信息的时候,一定要按照完整用户所占的字节进行读取100字节的整数倍
  * 第一个用户信息从0开始       第二个用户信息从100开始
  *2.根据上面分析可以根据当前文件的字节大小/100获取文件中存储用户的个数
  *3.可以根据用户不同信息所占的字节进行读取信息
  * @author cjn
  *
  */
 public class RAFSeeDemo {
 
  public static void main(String[] args) throws Exception {
  //指定文件user.txt进行读取用户信息
  RandomAccessFile raf = new RandomAccessFile("user.txt","r");
  //查看文件大小,确保是100字节的整数倍,进行后续拆分
  System.out.println("文件大小为"+raf.length()+"字节,存储了"+raf.length()/100+"个用户信息");
  //使用for循环遍历用户信息
  for (int i = 0; i < raf.length()/100; i++) {
  //读取用户名
  byte[] data = new byte[32];
  raf.read(data);
  String userName = new String(data,"gbk");
  //System.out.println(raf.getFilePointer());
 
  //读取昵称
  raf.read(data);
  String nickName = new String(data,"gbk");
  //System.out.println(raf.getFilePointer());
 
  //读取密码
  raf.read(data);
  String password = new String(data,"gbk");
  //System.out.println(raf.getFilePointer());
 
  //读取年龄
  int age = raf.readInt();
  //System.out.println(raf.getFilePointer());
 
  //打印输出每个用户的注册信息
  System.out.println("用户名:"+userName.trim()+",昵称:"+nickName.trim()+",密码:"+password.trim()+",年龄:"+age);
  }
  System.out.println("查询完毕!");
  //关闭资源
  raf.close();
  }
 
 }
 

输出结果:

 文件大小为300字节,存储了3个用户信息
 用户名:小红,昵称:xiaohong,密码:111111,年龄:11
 用户名:小黄,昵称:xiaohuang,密码:222222,年龄:12
 用户名:小蓝,昵称:xiaolan,密码:333333,年龄:13
 查询完毕!

 

3.修改用户密码业务需求

1.找到用户注册信息的文件

2.根据每位用户存储的信息占用100字节,进行查找用户为xxx名字的信息

3.然后找到该用户的密码位置,进行重新设定一个新密码

 package cn.tedu;
 
 import java.io.FileNotFoundException;
 import java.io.RandomAccessFile;
 import java.util.Arrays;
 import java.util.Scanner;
 
 /**
  *修改用户密码业务需求
  *1.找到用户注册信息的文件
  *2.根据每位用户存储的信息占用100字节,进行查找用户为xxx名字的信息
  *3.如果存在该用户,那么就修改为新的密码;如果用户不存在,就输出"查无此人"
  * @author cjn
  *
  */
 public class RAFChangePassword {
 
  public static void main(String[] args) throws Exception {
  //指定文件user.txt进行读写操作
  RandomAccessFile raf = new RandomAccessFile("user.txt","rw");
  Scanner sc= new Scanner(System.in);
  System.out.println("请输入用户名:");
  String name = sc.nextLine();
  boolean isUpdate = false;//标志位,用于记录是否修改过
  for (int i = 0; i < raf.length()/100; i++) {
  raf.seek(i*100);//用户名都在整百倍数处开始
  byte[] data = new byte[32];
  raf.read(data);//读数据
  String userName = new String(data,"gbk").trim();//去除两侧空格
  //用户名存在
  if(userName.equals(name)){
  raf.seek(i*100+64);//指向密码指针地址位置
  System.out.println("请输入密码:");
  String password = sc.nextLine();
  data = password.getBytes("gbk");//字符串转化为字节
  data = Arrays.copyOf(data, 32);//数组扩容到32字节
  raf.write(data);//写数据
  isUpdate = true;//更新标志位
  System.out.println("修改成功!");
  break;
  }
  }
  //用户名不存在
  if(!isUpdate){
  System.out.println("查无此人");
  }
  //关闭资源
  sc.close();
  raf.close();
  }
 }
 
posted @ 2021-06-18 15:54  Coder_Cui  阅读(173)  评论(0编辑  收藏  举报