Java 用IO流实现数据储存
一、Java 用IO流实现用户的注册与登录,并且将用户的账号密码储存
- 从文件中读取存储的用户名和密码,并且实现用户的注册和登录操作。
- 不使用Propreties类,而是使用IO流中的字节流读取信息,就需要使用String类的split方法,并且提前做好标记符号
- split方法是将字符串中按指定的符号分割开,比如"123#456",就变成"123",“456”,而且是个数组,所以可以通过split方法先分割开每个用户,然后再分割开每个用户的用户名和密码
- 这里没有把读取文件中的用户名和密码写成方法,所以在用户注册成功后又复制粘贴了一遍读取操作,看着有点累赘
- 因为是一个字节一个字节的读取文本,所以不能使用中文注册用户名,会乱码
import java.io.*;
import java.util.ArrayList;
import java.util.Scanner;
public class LoginSystemC {
public static void main(String[] args) throws IOException {
Scanner scanner = new Scanner(System.in);
File file = new File("C:\\Users\\hasee\\Desktop\\JAVA study\\JavaSE\\src\\com\\yaorange\\day18\\userInformationC.ini");
InputStream inputS = new FileInputStream(file);
OutputStream outputS = new FileOutputStream(file,true);//不写true的话会导致每次都是覆盖储存文件
ArrayList<String> users = new ArrayList<>();
boolean flag1 = true;
while (flag1) {//读取每个用户名与密码,以#为结尾,一个字符串一个字符串的写入
int read;
StringBuffer sB = new StringBuffer();
while ((read = inputS.read()) != '#') {
if (read == -1) {//读到末尾了,跳出
flag1 = false;
break;
}
sB.appendCodePoint(read);
}
if(flag1==false)
break;
users.add(sB.toString());//将用户写入用户列表
}
ArrayList<String> userlist = new ArrayList<>();//用户名列表
ArrayList<String> pwdlist = new ArrayList<>();//密码列表
for (String user1 : users) {
String arr[] = user1.split("-");//将用户名与密码分割开
userlist.add(arr[0]);
pwdlist.add(arr[1]);
}
boolean flag = true;
while (flag) {
System.out.println("1、注册 2、登录 3、退出");
int x = scanner.nextInt();
String dontneed = scanner.nextLine();
switch (x) {
case 1:
System.out.println("请输入用户名:");
String username = scanner.nextLine();
if (userlist.contains(username)) {
System.out.println("用户名存在,不能注册");
break;
} else {
System.out.println("请输入密码:");
String pwd = scanner.nextLine();
outputS.write((username+"-"+pwd+"#").getBytes());
System.out.println("用户注册成功");
//刷新刚注册的用户,不然会导致刚注册的用户无法登录
users = new ArrayList<>();
flag1 = true;
while (flag1) {
int read;
StringBuffer sB = new StringBuffer();
while ((read = inputS.read()) != '#') {
if (read == -1) {
flag1 = false;
break;
}
sB.appendCodePoint(read);
}
if(flag1==false)
break;
users.add(sB.toString());
}
userlist = new ArrayList<>();//用户名列表
pwdlist = new ArrayList<>();//密码列表
for (String user1 : users) {
String arr[] = user1.split("-");
System.out.println(user1);
userlist.add(arr[0]);
pwdlist.add(arr[1]);
}
break;
}
case 2:
System.out.println("请输入用户名:");
String s1 = scanner.nextLine();
if (userlist.contains(s1)) {
System.out.println("请输入密码:");
String pwdL = scanner.nextLine();
if (pwdL.equals(pwdlist.get(userlist.indexOf(s1))))
System.out.println("登录成功");
else System.out.println("密码输入错误");
break;
} else {
System.out.println("用户名不存在");
break;
}
case 3:
flag = false;
break;
}
}
inputS.close();
outputS.close();
scanner.close();
}
}
二、案例
1. 简易ATM机通过io流存储更改的用户数据
public class FileManager {
private static final String FILE_NAME = "users.dat";
//ObjectOutputStream 将 List<User> 对象写入到一个名为 users.dat 的文件中。
public static void saveUsers(List<User> users) {
//创建ObjectOutputStream对象,并将用户列表写入文件。如果发生IOException,会打印信息。
try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(FILE_NAME))) {
oos.writeObject(users);
} catch (IOException e) {
e.printStackTrace();
}
}
//使用 ObjectInputStream 从 users.dat 文件中读取 List<User> 对象。
public static List<User> loadUsers() {
List<User> users = new ArrayList<>();
//创建 ObjectInputStream 对象,并读取用户列表。如果文件未找到,则打印一条消息并初始化一个新的用户列表。
try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream(FILE_NAME))) {
users = (List<User>) ois.readObject();
} catch (FileNotFoundException e) {
System.out.println("用户数据文件未找到,初始化新数据。");
} catch (IOException | ClassNotFoundException e) {
e.printStackTrace();
}
System.out.println("...系统初始化成功");
return users; //返回读取的用户列表
}
}
- 初始化系统,并在在程序结束前,调用
FileManager.saveUsers(users)方法,将当前的用户列表保存到文件中。
public static void main(String[] args) {
users = FileManager.loadUsers(); //尝试加载用户数据,不存在返回空null
if (users.isEmpty()) {
initializeUsers(); //若为空则创建并初始化
}
showMainMenu();
FileManager.saveUsers(users); //结束前调用 saveUsers(users)
}
private static void initializeUsers() {
users = new ArrayList<>();
users.add(new User("111111", "111", 12000));
users.add(new User("222223", "222", 24000));
users.add(new User("333333", "333", 18500));
users.add(new User("444444", "444", 15000));
users.add(new User("555555", "555", 900));
users.add(new User("666666", "666", 6300));
users.add(new User("777777", "777", 7200));
users.add(new User("888888", "888", 18100));
users.add(new User("999999", "999", 9100));
users.add(new User("100000", "100", 20000));
}
2. 简易背包系统存储数据
- 创建一个
FileManager类来处理背包数据的保存和加载。- 修改
Backpack类,使其在每次更改数据时保存数据,并在初始化时加载数据。
1). 首先,我们定义一个 FileManager 类,用于保存和加载背包数据:
import java.io.*;
import java.util.List;
public class FileManager {
private static final String FILE_NAME = "backpack.dat";
public static void saveBackpack(Backpack backpack) {
try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(FILE_NAME))) {
oos.writeObject(backpack);
} catch (IOException e) {
e.printStackTrace();
}
}
public static Backpack loadBackpack() {
Backpack backpack = null;
try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream(FILE_NAME))) {
backpack = (Backpack) ois.readObject();
} catch (FileNotFoundException e) {
System.out.println("背包数据文件未找到,初始化新数据。");
backpack = new Backpack();
} catch (IOException | ClassNotFoundException e) {
e.printStackTrace();
}
System.out.println("...系统初始化成功");
return backpack;
}
}
2). 接下来,修改 Backpack 类,( 也就是你的主类 )使其在每次更改数据时保存数据
'''
public class Backpack implements Serializable { //将需要io操作的类实现Serializable接口
private List<Slot> slots;
private Wallet wallet;
'''
public void identifyItem(String nameOrId) {
for (Slot slot : slots) {
if (slot.getItem() != null && (slot.getItem().getName().equals(nameOrId) || slot.getItem().getId().equals(nameOrId))) {
if (slot.getItem().isIdentified()) {
JOptionPane.showMessageDialog(null, "该物品已被鉴定", "鉴定物品", JOptionPane.INFORMATION_MESSAGE);
} else {
slot.getItem().identify();
JOptionPane.showMessageDialog(null, "该物品鉴定完毕", "鉴定物品", JOptionPane.INFORMATION_MESSAGE);
//在每次发生数据修改时(增删改)都要调用一次saveBackpack()方法
FileManager.saveBackpack(this);
}
return;
}
}
JOptionPane.showMessageDialog(null, "鉴定物品不存在", "鉴定物品", JOptionPane.INFORMATION_MESSAGE);
}
'''
3). 更新 Main 类,使其在启动时加载背包数据,并在每次操作后保存数据:
public class Main {
public static void main(String[] args) {
// 加载背包数据
Backpack backpack = FileManager.loadBackpack();
while (true) {
String[] options = {"添加物品", "查询所有物品", "查询指定物品", "查询金钱", "鉴定物品", "交易物品", "销毁物品", "整理背包", "扩容背包", "退出"};
int choice = JOptionPane.showOptionDialog(null, "选择一个操作", "背包系统",
JOptionPane.DEFAULT_OPTION, JOptionPane.INFORMATION_MESSAGE, null, options, options[0]);
'''
注意:
如果提示错误:
Exception in thread "main" java.lang.NullPointerException: Cannot invoke "org.D0802.BackpackSystem.Backpack.addItem(String, int)" because "backpack" is null
at org.D0802.BackpackSystem.Main.addItem(Main.java:57)
at org.D0802.BackpackSystem.Main.main(Main.java:19)
-
检查
FileManager类:确保FileManager.loadBackpack()方法正确返回一个Backpack对象。 -
检查
Main类:确保在main方法中正确加载backpack对象。 -
确保
Backpack类及其所有依赖类(如Slot、Wallet、Item及其子类)都实现了Serializable接口。

浙公网安备 33010602011771号