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

发布于 2024-10-07 19:31:43 字数 909 浏览 5 评论 0原文

我在 Java 中有这样的代码:

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

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

  1. hello
  2. hey
  3. yo
  4. good-day

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

  1. hello\n
  2. hey\r
  3. yo\r\n
  4. goodday

我该怎么做?有我可以使用的现成课程吗?

--

更新:

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

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

在我的示例中,正在上传图像。图像数据在单行上发送。然而,图像的二进制数据包含读取器将解释为“\n”、“\r”或有时“\r\n”的字节(如果这两个字节恰好彼此相邻)。

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

I have this code in 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:

  1. hello
  2. hey
  3. yo
  4. good-day

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

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).

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.

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.

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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

如日中天 2024-10-14 19:31:43

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

这是我对您更具体的问题的回答(如何准确实现 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();
  }
}

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

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.

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:

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 readLine built into Java. It's likely that you will find similar, but not exactly matching readLines in a third-party .jar file. My recommendation is just to use the one above, if you really need that feature.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文