gpt4 book ai didi

Java OutputStream 读取字符串行

转载 作者:行者123 更新时间:2023-12-01 22:47:34 24 4
gpt4 key购买 nike

我使用一个 API(有关更多信息,请参阅下文),它接受 OutputStream 来捕获数据。相反,我想提供一个 ConsumerStrings 来消耗一行又一行的数据。因此我必须编写一个 OutputStream 实现来包装这样的 Consumer。这是我能想到的最简单的:

import java.io.OutputStream;
import java.util.Objects;
import java.util.function.Consumer;

public class OutputStreamConsumer extends OutputStream {

private final Consumer<String> consumer;
private final StringBuilder sb = new StringBuilder();

public OutputStreamConsumer(Consumer<String> consumer) {
this.consumer = Objects.requireNonNull(consumer);
}

@Override
public void write(int b) {
char c = (char) b;
if (c == '\r') {
return;
}
if (c == '\n') {
consume();
return;
}
this.sb.append(c);
}

@Override
public void close() {
if (sb.length() != 0) {
consume();
}
}

private void consume() {
this.consumer.accept(this.sb.toString());
this.sb.delete(0, Integer.MAX_VALUE);
}

}

但是,就编码性能而言,这对于生产代码来说可能还不够。我认为必要的逻辑已经包含在 InputStreamReaderBufferedReader 中,但我无法在这种情况下使用这些类。编写这种OutputStream的最佳方法是什么?我可以使用哪些 jdk 类来避免编写一堆处理编码、行尾等的低级代码。

具体用例

在 Gradle 插件项目中,我使用 Gradle 的项目 API 启动外部进程:ExecSpec 。我可以使用方法 setStandardOutputsetErrorOutput 设置 OutputStreams,以捕获进程的输出。

最佳答案

由于到目前为止还没有答案,我将在撰写本文时发布我的“最佳”解决方案。欢迎发布更好的解决方案。

import java.io.IOException;
import java.io.OutputStream;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.Objects;
import java.util.function.Consumer;

public class LineReadingOutputStream extends OutputStream {

private static final byte CR = '\r';
private static final byte LF = '\n';

private final Consumer<String> consumer;
private final StringBuilder stringBuilder = new StringBuilder();
private boolean lastCR = false;

private LineReadingOutputStream(final Consumer<String> consumer) {
this.consumer = Objects.requireNonNull(consumer);
}

@Override
public void write(final int b) throws IOException {
write(new byte[]{(byte) b});
}

@Override
public void write(final byte[] b, int start, final int len) {
if (b == null) {
throw new NullPointerException();
}
if (len < 0) {
throw new IllegalArgumentException();
}
final int end = start + len;
if ((start < 0) || (start > b.length) || (end < 0) || (end > b.length)) {
throw new IndexOutOfBoundsException();
}

if (this.lastCR && start < end && b[start] == LF) {
start++;
this.lastCR = false;
} else if (start < end) {
this.lastCR = b[end - 1] == CR;
}

int base = start;
for (int i = start; i < end; i++) {
if (b[i] == LF || b[i] == CR) {
final String chunk = asString(b, base, i);
this.stringBuilder.append(chunk);
consume();
}
if (b[i] == LF) {
base = i + 1;
} else if (b[i] == CR) {
if (i < end - 1 && b[i + 1] == LF) {
base = i + 2;
i++;
} else {
base = i + 1;
}
}
}
final String chunk = asString(b, base, end);
this.stringBuilder.append(chunk);
}

@Override
public void close() {
if (this.stringBuilder.length() != 0) {
consume();
}
}

private static String asString(final byte[] b, final int start, final int end) {
if (start > end) {
throw new IllegalArgumentException();
}
if (start == end) {
return "";
}
final byte[] copy = Arrays.copyOfRange(b, start, end);
return new String(copy, StandardCharsets.UTF_8);
}

private void consume() {
this.consumer.accept(this.stringBuilder.toString());
this.stringBuilder.delete(0, Integer.MAX_VALUE);
}
}

关于Java OutputStream 读取字符串行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58468441/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com