Java Servlet使用BufferedReader读取txt文件仅能读第一行如何修复
代码存在的问题
- 提前读取第一行后,仅对第一行的账号密码做了拆分赋值,循环内没有重新拆分新读取的行内容,
u和p永远是第一行的账号密码,无法匹配后续行的用户信息 - while循环的条件中已经执行了
br.readLine()读取行,循环体末尾又额外调用了一次br.readLine(),相当于每次循环跳过2行,会漏读内容 - 循环内的判断逻辑错误:if和else if的判断条件完全一致,无法区分管理员和普通用户;且只要当前读取的行不匹配就直接forward到登录失败页,请求直接终止,根本不会进入下一轮循环读取后续行
- BufferedReader使用后未关闭,存在资源泄漏问题
修复方案
修改后的完整代码如下:
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { HttpSession http = request.getSession(); String path = getServletContext().getRealPath("/WEB-INF/users.txt"); // 用try-with-resources自动关闭流,避免资源泄漏 try (BufferedReader br = new BufferedReader(new FileReader(new File(path)))) { String userName = request.getParameter("username"); String passWord = request.getParameter("password"); String account; boolean loginSuccess = false; boolean isAdmin = false; // 循环读取所有行,每行都拆分比对 while ((account = br.readLine()) != null) { // 跳过空行 if (account.trim().isEmpty()) { continue; } String[] split = account.split(","); String u = split[0].trim(); String p = split[1].trim(); if (userName.equals(u) && passWord.equals(p)) { loginSuccess = true; // 按原文件第一行为管理员账号的规则做判断,可根据实际需求调整规则 isAdmin = u.equals("admin"); break; } } // 所有行读取完成后再统一处理跳转逻辑,不要在循环里跳转 if (loginSuccess) { http.setAttribute("username", userName); if (isAdmin) { getServletContext().getRequestDispatcher("/WEB-INF/admin.jsp").forward(request, response); } else { getServletContext().getRequestDispatcher("/WEB-INF/inventory.jsp").forward(request, response); } } else { request.setAttribute("message", "The wrong username or password have been entered."); getServletContext().getRequestDispatcher("/WEB-INF/login.jsp").forward(request, response); } } }
核心修改点说明
- 用try-with-resources语法管理BufferedReader,自动释放资源无需手动关闭
- 将账号密码的拆分、比对逻辑移到循环内部,每次读取新行后都更新
u和p的值 - 删除循环内多余的
br.readLine()调用,避免漏读 - 循环内仅做匹配标记,不做跳转,等所有行读取完成后再根据匹配结果统一处理跳转,避免中途终止循环导致后续行无法读取
- 增加管理员账号判断逻辑,区分admin和普通用户的跳转路径
内容的提问来源于stack exchange,提问作者King
相关产品推荐
相关产品推荐

