You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

图书馆系统开发:如何让PrintWriter无需等待输入执行后续方法?

问题背景与描述

我开发了一个和MySQL交互的图书馆系统,客户端和服务器通过PrintWriter(变量名out)和Scanner进行通信。现在的问题是,服务器在发送完查询结果后,没法跳出等待输入的循环,没办法自动执行bookStoreMenu()方法。

我试过加换行符\n,但PrintWriter好像不生效;也尝试过在客户端和服务器用各种循环、布尔判断,都没解决问题。

客户端代码

socket = new Socket(IPaddress, port);
System.out.println("Connected to server at "+ IPaddress + ":" + port);
//Connect a Scanner to the socket's InputStream to read lines from it
in = new Scanner(socket.getInputStream());
//Connect a PrintWriter to the OutputStream to send lines to server
out = new PrintWriter(socket.getOutputStream(), true);
//Connect a Scanner to system input to take command line instructions
menu();

userInput = new Scanner(System.in);
while(userInput.hasNext()){
    out.println(userInput.nextLine());//handle output to server
    System.out.println(in.nextLine()); //print input from server
}

服务器代码片段

while (sqlExecute.next()) {
     int id = sqlExecute.getInt("bookID");
     String isbn = sqlExecute.getString("book_ISBN");
     String title = sqlExecute.getString("book_title");
     String author = sqlExecute.getString("book_author");
     String publisher = sqlExecute.getString("book_publisher");
     String language = sqlExecute.getString("book_language");
     //Building a string
     /*BookString = ("Book ISBN: " + isbn + ", Book Title: " + title + ",
         Author: " + author + ", Publisher: " + publisher + ", Language " +
        language);*/
     bookResults.append("BookID: " +id + ", Book ISBN: " + isbn);
     bookResults.append(", Title: " + title + ", Author: " + author);
     bookResults.append(", Publisher: " + publisher + ", Language: " + language);
     bookResults.append(" || ");
     System.out.printf("%s, %s, %s, %s, %s, %s\n", 
                       id, isbn, title, author, publisher, language + "\n");
}
//Sending results
out.println(bookResults + "\n");
bookStoreMenu();

解决方案

1. 定义通信边界:添加响应结束标记

问题核心是客户端和服务器的通信没有明确的结束信号,导致一方一直阻塞等待。你需要约定一个特殊字符串作为响应结束标记,让客户端知道当前批次的消息已发送完毕,避免卡在in.nextLine()。

修改服务器代码,发送完结果后追加结束标记:

//Sending results
out.println(bookResults.toString());
out.println("END_OF_RESPONSE"); // 新增结束标记
bookStoreMenu();

同步修改客户端循环逻辑,判断到结束标记就停止读取服务器响应:

userInput = new Scanner(System.in);
while(userInput.hasNext()){
    out.println(userInput.nextLine());//handle output to server
    // 循环读取直到收到结束标记
    String serverMsg;
    while (!(serverMsg = in.nextLine()).equals("END_OF_RESPONSE")) {
        System.out.println(serverMsg);
    }
}

2. 修复服务器的阻塞逻辑

你提供的服务器代码只展示了查询结果发送部分,推测服务器存在一个等待客户端输入的循环(比如用Scanner读取socket输入)。如果服务器一直卡在等待客户端指令的逻辑里,bookStoreMenu()就无法执行。

可以用多线程分离客户端请求处理和菜单逻辑,避免互相阻塞:

// 服务器接受连接后,启动独立线程处理客户端交互
new Thread(() -> {
    Scanner in = new Scanner(socket.getInputStream());
    PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
    
    // 处理客户端请求的循环
    while (in.hasNextLine()) {
        String clientCmd = in.nextLine();
        // 执行你的MySQL查询逻辑(即你提供的那段结果拼接代码)
        // ...
        // 发送结果和结束标记
        out.println(bookResults.toString());
        out.println("END_OF_RESPONSE");
        // 直接执行菜单方法,无需等待输入
        bookStoreMenu();
    }
}).start();

3. 修正PrintWriter的换行使用

out.println()方法会自动添加系统对应的行分隔符,不需要手动拼接"\n"。你创建PrintWriter时已经开启了自动刷新(第二个参数为true),所以每次调用println()都会立即把内容发送出去,不用担心缓冲区阻塞问题。直接用out.println(bookResults.toString())即可,多余的"\n"反而可能导致解析混乱。


内容的提问来源于stack exchange,提问作者Dfr444er

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.11 13:45:31