Java BufferedReader.readLine()没有等待EOL?

时间:2012-07-20 20:41:12

标签: java bufferedreader inputstreamreader bytearrayinputstream

很抱歉,如果我在这里遗漏了一些明显的东西......但请看一下这段代码:

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')或回车符后面的任何一个终止。

     

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

我看不出为什么我的字符串会被重新解释为以'\ n'和/或'\ r'终止的任何原因...有人可以照亮我吗?谢谢!

修改: 为了提供一些上下文,我正在尝试编写JUnit测试以验证我编写的读取器类,该类旨在读取System.in。使用ByteArrayInputStreams似乎是模拟System.in的合理方法(参见this relevant SO post)。

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

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

再次感谢!

5 个答案:

答案 0 :(得分:3)

ByteArrayInputStream在耗尽时不会返回EOL。它只返回-1,可能被认为是EOF。

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

因此,如果你想要非常严格,你可以说readLine()根据当前的文档是borken,或者如果这是预期的行为,它应该以不同的方式记录。

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

答案 1 :(得分:1)

我想这会阻止您从真正的流(例如网络套接字)中读取。但由于底层输入是一个数组,读者知道已达到数据的真正结束,因此不需要阻塞,因为没有新的数据即将到来。所以阻塞将是一个错误的行动方案。在读取实际数据的地方返回null也是一件错误的事情。

答案 2 :(得分:1)

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

        

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

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

答案 3 :(得分: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);
}

答案 4 :(得分:0)

现在唯一的替代方法是抛弃最后一条不完整的线。不可取。