0

这是我的代码:

public static void main(String[] args) {
        String in = "";
        
        InputStreamReader reader = new InputStreamReader(System.in);
        
        int ch;
        StringBuilder sb = new StringBuilder();
        
        System.out.println("paste text below:");
        
        try {
            while ((ch = reader.read()) != -1 && ch != 0) {
                sb.append((char)ch);
            }
        }catch (IOException e) {
            System.err.println(e.toString());
        }
    }
    in = sb.toString();
    System.out.println(in);
}

我已经调试过了,它会遍历所有内容并在换行符上打印每个字符,但是在读取最后一个字符后它会一直停止。我已经简单地输入asdfasdf并复制了独立宣言并粘贴了它。它一直运行到结束,然后停止。

它甚至不像是一个无限循环,因为我在代码的每个部分都放了一个 System.out.print("!@#$%") ,它就停止了……我的代码中没有无限循环。我很确定InputStreamReader-- reader-- 卡在它自己的无限循环中,因为它永远不会返回-1。事实上,当它结束时它永远不会返回任何东西(尽管它在循环中返回正确的整数/字符)。

有谁知道发生了什么或者有没有人遇到过类似的问题?有没有办法解决这个问题(不要说 BufferedReader 因为我需要读取带有多个换行符的文本,而 BufferedReader 搜索第一个\n,所以我不能使用它)?

编辑:

我尝试读取字符缓冲区,然后使用字符串生成器......什么都没有。

回答:

您必须提供一个会打破循环的字符(否则请参阅@default locales 的答案)。

这是我的代码演变成的内容:

public static void main(String[] args) {
    InputStreamReader reader = new InputStreamReader(System.in);
    StringBuilder sb = new StringBuilder();
    
    int ch;
    
    System.out.println("Paste text below (enter or append to text \"ALT + 1\" to exit):");
    
    try {
        while ((ch = reader.read()) != (char)63 /*(char)63 could just be ☺*/) {
            sb.append(ch);
        }
        reader.close();
    }catch (IOException e) {
        System.err.println(e.toString());
    }
    String in = sb.toString();
    System.out.println(in);
}

Alt + 1返回(至少在 Windows 上)返回笑脸图标,但你可以做任何你想要的组合键,你所要做的就是找出 java 中的 char 并做while ((ch = reader.read()) != (char)charNumber.

4

2 回答 2

1

System.in是一个BufferedInputStream,试试这个:

System.err.println(System.in.getClass());

所以你可能会遇到这种停滞的行为,因为缓冲区会等待更多的数据,有时它会被刷新,有时不会。

如果 System.in 是用户通过键盘输入的,它将在 Ctrl-Z (Windows) 或 Ctrl-D (*nix) 上停止。

如果你想从键盘读取用户输入,你应该使用Console

于 2014-07-30T16:26:27.210 回答
1

基本上,reader.read()内部调用InputStream.read。这是来自文档的引用:

从输入流中读取数据的下一个字节。值字节作为 int 返回,范围为 0 到 255。如果由于到达流的末尾而没有可用的字节,则返回值 -1。此方法会一直阻塞,直到输入数据可用、检测到流结束或引发异常。

换句话说,此方法将阻止程序执行并永远等待您的输入。

现在您可以看到处于当前状态的程序将永远不会停止执行:

//wait for user input forever
while ((ch = reader.read()) != -1 && ch != 0) {
    //no matter what the input is just print it
    System.out.println((char)ch);
} //continue waiting...

可能的解决方案:

  • 自定义退出策略,例如当用户进入时打破循环Ω,或者当用户连续三次输入“KILL ME”时,或者在200个第一个字符之后。
  • 在命令窗口中输入特殊的 End-Of-File 组合以关闭System.in. 这种方法通常涉及一些特定于操作系统/终端的 hack。看看这个问题:如何通过 Windows 终端发送 EOF
  • 实现非阻塞读取机制。看看这个问题:Is it possible to read from a InputStream with a timeout?

之前在 Stackoverflow 上已经提出了类似的问题:

于 2014-07-30T16:33:57.133 回答