从 Java 中的输入流中读取一行文本,保留行终止字符

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/4445740/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-14 17:35:39  来源:igfitidea点击:

Read a line of text from an input stream in Java keeping the line-termination character(s)

javalineinputstream

提问by Mike

I have this code in Java:

我在 Java 中有这个代码:

InputStreamReader isr = new InputStreamReader(getInputStream());
BufferedReader ir = new BufferedReader(isr);
String line;
while ((line = ir.readLine()) != null) {
 //do stuff with "line"
}

If the input stream contains the following: "hello\nhey\ryo\r\ngood-day", then line variable would be following on each iteration:

如果输入流包含以下内容:“hello\nhey\ryo\r\ngood-day”,则每次迭代都会跟随行变量:

  1. hello
  2. hey
  3. yo
  4. good-day
  1. 你好
  2. 再会

I want to read one line at a time, but I want to keep the line-termination character(s):

我想一次读一行,但我想保留行终止符:

  1. hello\n
  2. hey\r
  3. yo\r\n
  4. good-day
  1. 你好\n
  2. 嘿\r
  3. 哟\r\n
  4. 再会

How can I do this? Is there a ready-made classes I can use?

我怎样才能做到这一点?我可以使用现成的课程吗?

--

——

Update:

更新:

Here's what I'm trying to do and why I need to keep the end-of-line character (and why the EOL character may be different).

这就是我想要做的事情以及为什么我需要保留行尾字符(以及为什么 EOL 字符可能不同)。

I'm reading a POST request. They consists of pure text messages where the lines always end with \r\n (by the standard specification). However POST request may contain binary data, which may contain bytes that look like termination characters to Java Reader objects.

我正在阅读 POST 请求。它们由纯文本消息组成,其中行始终以 \r\n 结尾(按照标准规范)。然而,POST 请求可能包含二进制数据,这些数据可能包含看起来像 Java Reader 对象的终止字符的字节。

In my example, an image is being uploaded. The image data is sent on a single line. However, however the image's binary data contains bytes that the READER would interpret as "\n", "\r" or sometimes "\r\n" if those two bytes happens to be next to each other.

在我的示例中,正在上传图像。图像数据在单行上发送。然而,图像的二进制数据包含字节,如果这两个字节碰巧彼此相邻,则 READER 会将其解释为“\n”、“\r”或有时会解释为“\r\n”。

I have to read the POST request one line at a time because that's how it works. I suppose, I COULD read everything and then parse the whole thing. But that's not efficient, especially if a large file (say 1024 MiB) file is being uploaded.

我必须一次读取一行 POST 请求,因为它就是这样工作的。我想,我可以阅读所有内容,然后解析整个内容。但这效率不高,尤其是在上传大文件(例如 1024 MiB)文件时。

采纳答案by pts

If you want to read a HTTP POST request, I strongly suggest using BufferedInputStream.read()(not BufferedReader!) directly (without readLine-like intermediate abstractions), paying attention to all details manually, including the handling of CR and LF according to the HTTP RFC.

如果您想读取 HTTP POST 请求,我强烈建议直接使用BufferedInputStream.read()(而不是BufferedReader!)(没有readLine类似中间抽象),手动注意所有细节,包括根据 HTTP RFC 处理 CR 和 LF。

Here is my answer to your more specific question (how to implement exactly that readLine). This might not be the fastest solution, but it's time complexity is optimal, and it works:

这是我对您更具体问题的回答(如何准确地实现该问题readLine)。这可能不是最快的解决方案,但它的时间复杂度是最佳的,并且它有效:

import java.io.BufferedReader;
import java.io.IOException;   
public class LineReader {   
  private int i = -2;
  private BufferedReader br;
  public OriginalLineReader(BufferedReader br) { this.br = br; }
  public String readLine() throws IOException {
    if (i == -2) i = br.read();
    if (i < 0) return null;
    StringBuilder sb = new StringBuilder();
    sb.append((char)i);
    if (i != '\r' && i != '\n') {
      while (0 <= (i = br.read()) && i != '\r' && i != '\n') {
        sb.append((char)i);
      }
      if (i < 0) return sb.toString();
      sb.append((char)i);
    }
    if (i == '\r') {
      i = br.read();
      if (i != '\n') return sb.toString(); 
      sb.append((char)'\n');
    }
    i = -2;
    return sb.toString();
  }
}

You won't find such a readLinebuilt into Java. It's likely that you will find similar, but not exactly matching readLines in a third-party .jarfile. My recommendation is just to use the one above, if you really need that feature.

您不会readLine在 Java 中找到这样的内置功能。您很可能会readLine在第三方.jar文件中找到类似但不完全匹配的s 。如果您确实需要该功能,我的建议是仅使用上述功能。