读取 Java BufferedReader 的所有内容,包括行终止字符

Reading all content of a Java BufferedReader including the line termination characters

我正在编写一个 TCP 客户端,它接收一些二进制数据并将其发送到设备。当我使用 BufferedReader 读取它收到的内容时出现问题。

我非常困惑,发现没有方法可以读取所有数据。每个人都在使用的 readLine() 方法将 \n\r 字符都检测为行终止字符,所以我无法获取数据并连接行,因为我不知道which char 是行终止符。我也不能使用 read(buf, offset, num),因为它没有 return 它读取的字节数。如果我使用 read() 方法逐字节读取它,它会变得非常慢。请有人告诉我解决方案是什么,这个 API 对我来说似乎很愚蠢!


嗯,首先感谢大家。我认为主要问题是因为我阅读了 tutorialspoint 而不是 Java 文档。但请原谅我,因为我住在伊朗,而且 Oracle 出于某种原因不允许我们访问该文档。无论如何,感谢您的耐心和有益的答复。

我能推荐的最好的方法是使用 BufferedReader.read() 并遍历文件中的每个字符。像这样:

String filename = ...
br = new BufferedReader( new FileInputStream(filename));
while (true) {
   String l = "";
   Char c = " ";
   while (true){
        c = br.read();
        if not c == "\n"{
        // do stuff, not sure what you want with the endl encoding
        // break to return endl-free line
    }
    if not c == "\r"{
        // do stuff, not sure what you want with the endl encoding
        // break to return endl-free line
        Char ctwo = ' '
        ctwo = br.read();
        if ctwo == "\n"{
            // do extra stuff since you know that you've got a \r\n
        }
    }
    else{
        l = l + c;
    }
   if (l == null) break;
    ...
   l = "";
}

之前由@https://whosebug.com/users/615234/arrdem

回答

首先每个读取数据的人都必须将\n,\r,\r\n作为可能的序列进行规划,除非在解析HTTP头时必须用\r\n分隔。您可以轻松地逐行阅读并输出您喜欢的任何行分隔符。

其次是 read 方法 returns 它已读入 char[] 的字符数,因此如果您想读取一大块字符并进行自己的行解析和输出,它可以完全正确地工作。

这很可能是 XY 问题。

您问题的开头是:

I'm writing a TCP client that receives some binary data and sends it to a device. The problem arises when I use BufferedReader to read what it has received.

这是二进制数据; 不要使用 Reader 开始! Reader 使用字符集包装 InputStream 并产生 char 的流,而不是 byte秒。有关更多详细信息,请参阅 here 以及其他来源。

下一个:

I'm extremely puzzled by finding out that there is no method available to read all the data

有道理。不知道数据有多大,因此如果您收到的数据太大,这种方法会充满问题。

所以,现在使用 Reader 已经不可行了,您真正需要做的是:

  • Socket;
  • 中读取一些二进制数据
  • 将此数据复制到另一个来源。

这样做的解决方案有很多;这是一种解决方案,只需要标准 JDK (7+):

final byte[] buf = new byte[8192]; // or other

try (
    final InputStream in = theSocket.getInputStream();
    final OutputStream out = whatever();
) {
    int nrBytes;
    while ((nrBytes = in.read(buf)) != -1)
        out.write(buf, 0, nrBytes);
}

将此代码包装在方法或其他内容中

I'm extremely puzzled by finding out that there is no method available to read all the data.

三个。

The readLine() method that everybody is using, detects both \n and \r characters as line termination characters, so I can't get the data and concat the lines, because I don't know which char was the line terminator.

正确。记录了抑制行终止符。

I also can't use read(buf, offset, num), because it doesn't return the number of bytes it has read.

它 return 是读取的 个字符 的数量。

If I read it byte by byte using read() method, it would become terribly slow.

它是逐字符读取的,而不是逐字节读取的,但是您对性能的理解是错误的。它被缓冲了。

Please someone tell me what is the solution

首先您不应该对二进制数据使用 Reader。我只能建议您重新阅读 Javadoc:

BufferedInputStream.read() throws IOException;
BufferedInputStream.read(byte[]) throws IOException;
BufferedInputStream.read(byte[], int, int) throws IOException;

最后两个都是 return 读取的字节数,或者流末尾的 -1。

this API seems quite stupid to me!

无评论。