4

对不起,如果我在这里遗漏了一些明显的东西......但请看一下这段代码片段:

String readString;
String writeString = "O hai world.";
BufferedReader br = new BufferedReader(
    new InputStreamReader( 
        new ByteArrayInputStream(writeString.getBytes()),
        "UTF-8"),
    1024);
readString = br.readLine();
System.out.println("readString: " + readString);

我希望这会打印“readString:null”,因为我认为 BufferedReader 在检测到有效 EOL 之前会遇到 EOF,但它会打印“readString:O hai world”。这似乎与 BufferedReader 的 Javadocs 所说的 readLine() 将做的相反:

读取一行文本。一行被认为是由换行符 ('\n')、回车符 ('\r') 或紧跟换行符的回车符中的任何一个终止的。

返回: 包含行内容的字符串,不包括任何行终止字符,如果已到达流的末尾,则返回 null

我看不出我的字符串会被重新解释为以 '\n' 和/或 '\r' 结尾的任何理由......有人可以照亮我吗?谢谢!

编辑:为了提供一些上下文,我正在尝试编写 JUnit 测试来验证我编写的旨在在 System.in 上读取的 Reader 类。使用 ByteArrayInputStreams 似乎是模拟 System.in 的一种合理方式(请参阅此相关 SO 帖子)。

当我的阅读器捕获一行时,它当前依赖于 BufferedReader.readLine()。出于我的目的,我的读者行必须都以 '\n' 或 '\r' 结尾;遇到没有 EOL 的 EOF 不应解析为有效行。所以我想我此时的问题实际上如下(我会在有时间的时候自己更详细地测试这些问题,但希望你们聪明的人能帮助我):

  • BufferedReader.readLine() 是否损坏/错误记录?或者当它的字节数组用完时,ByteArrayInputStream 是否返回了错误的东西?
  • 这种测试我的阅读器的方法是否错误,我是否应该期望 readLine() 在针对 System.in 使用时正常运行?我倾向于相信这个问题的答案是肯定的。
  • 有没有更好的方法来模拟 System.in 以进行单元测试?
  • 如果我需要在从 InputStream 读取时严格区分“\n”和“\r”,我最好编写自己的 readLine() 方法吗?如果是这种情况,我会感到非常惊讶。

再次感谢!

4

5 回答 5

3

ByteArrayInputStream 用尽时不会返回 EOL。它只返回可能被视为 EOF 的 -1。

问题是 BufferedReader 缓冲它从输入流中读取的所有内容,如果在任何 EOL 字符出现之前遇到 EOF(-1),它会返回缓冲到该点的字符串。

所以,如果你想非常严格,你可以说 readLine() 要么根据当前文档被破坏,要么如果这是预期的行为,它应该以不同的方式记录。

在我看来,考虑到流中的最后一行不必以 EOL 字符结尾(EOF 就足够了), readLine 的当前行为是正确的,即因为遇到 EOF 而读取了一行。因此,应该更改文档。

于 2012-07-20T22:02:16.113 回答
1

我想这会阻止您从真正的流(例如网络套接字)中读取。但是由于底层输入是一个数组,读者知道已经到达了数据的真正末尾,因此没有必要进行阻塞,因为没有新数据即将到来。因此,阻止将是错误的做法。返回读取实际数据的空值也是错误的做法。

于 2012-07-20T20:51:20.863 回答
1

我相信您想要一个“机器人”来模拟击键以进行测试:

此类用于生成本地系统输入事件,用于测试自动化、自运行演示和其他需要控制鼠标和键盘的应用程序。Robot 的主要目的是促进 Java 平台实现的自动化测试。

这是一篇进一步讨论它的文章:

于 2012-07-21T16:43:08.490 回答
0

你希望这个版本的代码会发生什么?

String readString;
String writeString = "O\nhai\nworld.";
BufferedReader br = new BufferedReader(
    new InputStreamReader( 
        new ByteArrayInputStream(writeString.getBytes()),
        "UTF-8"),
    1024);
while (true) {
    readString = br.readLine();
    if (readString == null) break;
    System.out.println("readString: " + readString);
}
于 2012-07-20T21:45:18.447 回答
0

它现在所做的唯一替代方法是将最后的不完整行扔掉。不可取。

于 2012-07-21T05:09:15.540 回答