Java图书馆系统GUI文件展示及NumberFormatException问题求助
一、先搞定NumberFormatException错误
从错误栈和你的代码来看,这个异常的根源很明确:你调用stringToLong()时传入了字符串"Book issued successfully"——而这个字符串正是你在Issue按钮点击后设置到NUM文本框的反馈信息。问题在于,为什么点击「显示已借书籍」的按钮会触发这个解析错误?
可能的原因及修复方案:
文本框引用搞混了
检查你ActionListener里「Print details of books issued to member」的代码块,确认调用stringToLong()时传入的是cpr.getText()而不是NUM.getText()。如果不小心写成了stringToLong(NUM.getText()),就会把之前Issue按钮留下的提示文本当成数字解析,直接抛出异常。正确的代码应该是:
long cprNum = stringToLong(cpr.getText()); // 确保这里是cpr文本框,不是NUMIssue按钮错误修改了cpr文本框
检查Issue按钮的代码,确认你是给NUM文本框设置反馈,而不是cpr文本框。如果误写为cpr.setText("Book issued successfully"),那么用户后续输入CPR时,文本框里会残留这个字符串,导致解析失败。正确的Issue按钮代码:
if (ITLib.issueBook(an, cpr)) NUM.setText("Book issued successfully"); // 确认是NUM,不是cpr else NUM.setText("Book couldn't be issued. Try again later.");给输入加一层验证
为了避免类似问题,建议在调用stringToLong()前先校验输入是否为合法数字。可以给stringToLong()方法添加前置检查:private static long stringToLong(String stringObject) throws NumberFormatException { String trimmed = stringObject.trim(); if (trimmed.isEmpty() || !trimmed.matches("\\d+")) { throw new NumberFormatException("Invalid number input: " + trimmed); } return Long.parseLong(trimmed); }然后在ActionListener中捕获异常,给用户友好提示:
case "Print details of books issued to member": { try { long cprNum = stringToLong(cpr.getText()); ITLib.printBooksIssued(cprNum); } catch (NumberFormatException e) { fName.setText("Error: Please enter a valid CPR number."); } catch (IOException e1){ fName.setText("Error. Make sure CPR number is correct and try again."); } }
二、实现点击按钮自动打开文件的正确姿势
你已经用到了Desktop.getDesktop().open(file),但需要完善一些细节来确保稳定性:
优化后的printBooksIssued方法:
void printBooksIssued(long cpr) throws IOException { File file = new File("d:/work/test.txt"); // 先保存原始的System.out,避免后续打印都被定向到文件 PrintStream originalOut = System.out; try { System.setOut(new PrintStream(new FileOutputStream(file))); int memberIndex = searchMember(cpr); if (memberIndex == -1) { System.out.println("Member doesn't exist."); } else { // 直接用searchMember返回的索引获取会员,不用循环遍历 LibMember m = membersList.get(memberIndex); System.out.println(Arrays.toString(m.getBooksIssued())); } } finally { // 必须恢复原始输出流,否则后续GUI的反馈会消失 System.setOut(originalOut); } // 打开文件前先检查文件是否存在 if (!file.exists()) { throw new IOException("File not found: " + file.getAbsolutePath()); } try { Desktop.getDesktop().open(file); } catch (UnsupportedOperationException e) { // 处理无桌面环境的情况(比如服务器) System.err.println("Opening files is not supported on this system."); } }
关键优化点:
- 恢复System.out:重定向输出流后一定要恢复,否则后续所有
System.out.println()都会输出到文件,导致GUI中看不到其他操作反馈。 - 文件存在性检查:打开前确认文件已创建,避免抛出文件不存在的异常。
- 捕获UnsupportedOperationException:某些环境(如Linux无桌面环境、服务器)不支持Desktop类,需要捕获这个异常并给出提示。
- 优化会员查找逻辑:你已经有
searchMember(cpr)方法返回索引,直接用这个索引获取会员即可,不用再循环遍历,提升效率。
额外小建议
尽量避免用System.setOut重定向输出到文件,直接用PrintWriter写入文件会更清晰,也不会影响全局输出:
try (PrintWriter writer = new PrintWriter(file)) { int memberIndex = searchMember(cpr); if (memberIndex == -1) { writer.println("Member doesn't exist."); } else { LibMember m = membersList.get(memberIndex); writer.println(Arrays.toString(m.getBooksIssued())); } }
这种方式不需要恢复System.out,代码更简洁安全。
内容的提问来源于stack exchange,提问作者Ramsha Khalid

