如何用ObjectInputStream读取Account实例列表并实现账号创建校验
问题描述
需要创建Account类实例,要求实例的handle不能与其他账号重复,通过for循环将传入的handle与已有账号的handle对比,若已存在则抛出IllegalHandleException异常。当前需要解决的是:如何从文件中读取得到账号实例列表,即以下代码中//listOfAccounts=list of each account注释处应替换为哪些代码?
原代码如下:
public int createAccount(String handle) throws IllegalHandleException{ //checks if handle is already taken FileInputStream accountsFile=new FileInputStream("listOfAccounts.txt"); ObjectInputStream in=new ObjectInputStream(accountsFile); //listOfAccounts=list of each account for (Account accounts : listOfAccounts){ if (handle==accounts.getHandle()){ throw new IllegalHandleException("Handle Is Already Taken"); } } //create account Account newAccount; newAccount=new Account(handle); //add account to the stream FileOutputStream updatedAccountsFile=new FileOutputStream("listOfAccounts.txt"); updatedAccountsFile.write(newAccount.getUserID()); ObjectOutputStream out=new ObjectOutputStream(updatedAccountsFile); //return ID return newAccount.getUserID(); }
解决方案
1. 读取账号列表的核心代码
假设listOfAccounts.txt文件中存储的是序列化后的List<Account>对象(你使用ObjectInputStream说明是基于对象序列化存储),注释处可替换为:
// 读取序列化的账号列表并强转为List<Account> List<Account> listOfAccounts = (List<Account>) in.readObject();
2. 原代码的关键修正(必须修复)
除了读取列表的问题,原代码还有几个逻辑错误需要修正:
- 字符串比较错误:Java中字符串内容比较不能用
==,必须用equals()方法,否则会导致重复判断失效:// 替换原if判断 if (handle.equals(accounts.getHandle())) { throw new IllegalHandleException("Handle Is Already Taken"); } - 文件写入逻辑错误:原代码直接写入
userID且覆盖文件的方式完全错误,应该将新账号添加到读取到的列表中,再将整个列表序列化写入文件:// 先把新账号加入列表 listOfAccounts.add(newAccount); // 用ObjectOutputStream写入完整列表 ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("listOfAccounts.txt")); out.writeObject(listOfAccounts); - 资源泄漏问题:所有IO流需要在使用后关闭,建议用try-with-resources语法自动关闭:
// 示例:用try-with-resources包裹IO操作 try (FileInputStream accountsFile = new FileInputStream("listOfAccounts.txt"); ObjectInputStream in = new ObjectInputStream(accountsFile)) { // 读取列表的代码放在这里 } catch (IOException | ClassNotFoundException e) { e.printStackTrace(); } - 首次创建账号的情况处理:如果是第一次创建账号,文件可能不存在,需要捕获
FileNotFoundException并初始化空列表:List<Account> listOfAccounts; try (FileInputStream accountsFile = new FileInputStream("listOfAccounts.txt"); ObjectInputStream in = new ObjectInputStream(accountsFile)) { listOfAccounts = (List<Account>) in.readObject(); } catch (FileNotFoundException e) { // 文件不存在,初始化空列表 listOfAccounts = new ArrayList<>(); } catch (IOException | ClassNotFoundException e) { throw new RuntimeException("读取账号列表失败", e); }
修正后的完整代码示例
public int createAccount(String handle) throws IllegalHandleException { List<Account> listOfAccounts; // 读取已有账号列表,处理文件不存在的情况 try (FileInputStream accountsFile = new FileInputStream("listOfAccounts.txt"); ObjectInputStream in = new ObjectInputStream(accountsFile)) { listOfAccounts = (List<Account>) in.readObject(); } catch (FileNotFoundException e) { listOfAccounts = new ArrayList<>(); } catch (IOException | ClassNotFoundException e) { throw new RuntimeException("读取账号列表失败", e); } // 校验handle是否重复 for (Account account : listOfAccounts) { if (handle.equals(account.getHandle())) { throw new IllegalHandleException("Handle Is Already Taken"); } } // 创建新账号并加入列表 Account newAccount = new Account(handle); listOfAccounts.add(newAccount); // 将更新后的列表写入文件 try (FileOutputStream updatedAccountsFile = new FileOutputStream("listOfAccounts.txt"); ObjectOutputStream out = new ObjectOutputStream(updatedAccountsFile)) { out.writeObject(listOfAccounts); } catch (IOException e) { throw new RuntimeException("写入账号列表失败", e); } return newAccount.getUserID(); }
注意:
Account类必须实现Serializable接口,否则无法完成对象的序列化与反序列化操作。
内容的提问来源于stack exchange,提问作者Samuel W
相关产品推荐
相关产品推荐

