【问题标题】:flush() does not flush on a Process OutputStreamflush() 不会在 Process OutputStream 上刷新
【发布时间】:2016-06-12 11:23:33
【问题描述】:

我尝试了多种方法来做到这一点:在每个“flush()”之后延迟 1 秒打印到进程输出流。 但是冲洗似乎没有按预期工作。有人能告诉我为什么吗?当调用“close()”时,我得到的是一个组合 String。在“close()”生效之前不会打印任何内容。

上下文:这应该会关闭我的 Minecraft 服务器并在之后运行备份。

    BufferedWriter w = new BufferedWriter(new OutputStreamWriter(process.getOutputStream()));
w.write("say Serverbackup begins in 3...");
w.flush();
Thread.sleep(1000);
w.write("say 2...");
w.flush();
Thread.sleep(1000);
w.write("say 1...");
w.flush();
Thread.sleep(1000);
w.write("say GAME OVER!!!!!!!!!!!!!...");
w.flush();
w.write("stop");
w.flush();
w.close();
process.waitFor(10, TimeUnit.SECONDS);
//...

【问题讨论】:

  • 这段代码的输出是什么??
  • @SanketGupte 在控制台上看起来像这样:say Serverbackup begins in 3...say 2...say 1...say GAME OVER!!!!!!!!!!!!!...stop。一根弦。 “停止”实际上会充当命令,但显然不是,因为它连接到其余部分。
  • 不应该吗?我的意思是,根据您的代码,“stop”被视为字符串,因为您将它作为参数传递给 write() 方法。
  • @SanketGupte 是的,应该。但作为“独立”字符串。 :) 我需要分别打印每个“写”命令。

标签: java process io stream bufferedwriter


【解决方案1】:

发生的情况是,当您刷新代码时,它实际上会清除上次通过连接打印的所有数据,并清除建立连接的通道。因此,它继续在同一行附加字符。在每个字符串前后添加“\n”。例如, w.write("\n say1..."); 这会将您的每个字符串打印在单独的行上。这会将每个字符串打印在新行上。

【讨论】:

  • 问题是,所有这些都是一次性打印出来的。但是有一个内置的“睡眠”在每次“打印”后等待 1 秒。这行不通。它会休眠 3 秒,然后立即打印所有内容。
  • 好的..所以你的意思是代码在后台正常执行,但它没有以所需的方式显示输出,对吧???
  • 谢谢,现在可以使用了。我认为将 \n 放在每个命令的末尾是一个更好的主意。谢谢你的帮助。 :)
【解决方案2】:

正如 Sanket Gupte 回答的那样,您必须在消息末尾添加“\n”, 因为您使用 .readline() 读取了进程的输入流(我想), 它只会在出现 \n 时打印,无论您的 Thread.sleep(..) 调用如何。并且冲洗按您的预期工作。它将缓冲区写入流。

  • 我认为这不是过程的问题,因为我不知道
  • 您在后台运行的内容我启动了 bash 并通过 echo 输出

    ProcessBuilder processBuilder = new ProcessBuilder("/bin/bash");
    processBuilder.redirectErrorStream(true);
    try {
        final Process bash = processBuilder.start();
        BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(bash.getOutputStream()));
    
        new Thread(new Runnable() {
            public void run() {
                BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(bash.getInputStream()));
                String line;
                try {
                    while ((line = bufferedReader.readLine()) != null){
                        System.out.println(line);
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }).start();
        bufferedWriter.write("echo say Serverbackup begins in 3...\n");
        bufferedWriter.flush();
        Thread.sleep(2000);
        bufferedWriter.write("echo say 2\n");
        bufferedWriter.close();
    
    } catch (IOException e) {
        e.printStackTrace();
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    

Serverbackup 从 3 开始...

...(2 秒)

说 2

【讨论】:

  • 这真的有效吗?这正是我所拥有的,除了“\ n”。但是每次打印之间的时间延迟不会打印我的消息。
  • 那么您为什么不添加“\n”,正如我们在答案中所写的那样?这就是我想让你解释的一点。如果您不在消息末尾添加它,则不会有“时间延迟”。
  • java doc -> public String readLine():读取一行文本。行被视为由换行符 ('\n')、回车符 ('\r') 或回车符后紧跟换行符中的任何一个终止。
  • 嗯,这是有道理的,wtf。我没有尝试它,因为我写的时候不在电脑上。我会尽快检查这是否能解决我的问题。谢谢你:)
  • 感谢朋友,成功了。我会接受这个答案,因为它是最具体的一个。我不知道控制台实际上是这样工作的,我认为它会立即获取并执行它,但这会让所有不使用缓冲流的人生活困难。
猜你喜欢
  • 1970-01-01
  • 2011-02-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-01-13
  • 1970-01-01
  • 1970-01-01
  • 2014-02-25
相关资源
最近更新 更多