gpt4 book ai didi

java - 创建正确处理两字节字符的自定义 OutputStream

转载 作者:行者123 更新时间:2023-12-02 14:09:28 25 4
gpt4 key购买 nike

基本上,我想将控制台输出重定向到 javafx TextArea。我现在正在使用此代码。

public static void init() {
//GUI code. TextArea variable is named textArea
Console console = new Console(textArea);
PrintStream ps = new PrintStream(console, true);
System.setOut(ps);
System.setErr(ps);
}

public static class Console extends OutputStream {

private TextArea output;
private PrintStream out;

public Console(TextArea ta) {
this.output = ta;
out = System.out;
}

@Override
public void write(int i) throws IOException {
Platform.runLater(() -> {
output.appendText(String.valueOf((char) i));
out.print(String.valueOf((char) i));

});


}

但是,有一个问题。 ASCII 字符工作得很好(因为它们都只使用一个字节)。但是,当我尝试打印需要两个字节进行编码的符号(例如西里尔字符)时,它们显然无法正确打印,我得到类似的东西

java.io.IOException: ￐ᄀ￐ᄌ￑チ￑ツ￐ᄉ￐ᄐ￐ᄉ ￐ᄑ￐ᄉ ￑テ￐ᄡ￐ᄚ￐ᄉ￑ツ￑チ￑マ ￐ᄑ￐ᄚ￐ᄍ￑ツ￐ᄌ ￑テ￐ᄎ￐ᄚ￐ᄋ￐ᄚ￐ᄑ￐ᄑ￑ヒ￐ᄍ ￐﾿￑テ￑ツ￑フ

有什么办法可以解决这个问题吗?也许使用不同的方法?

更新

这是我最后想到的。思考是否可以以某种方式优化它。

public static class Console extends OutputStream {

private TextArea output;
private PrintStream out;
private ArrayList<Byte> bytes = new ArrayList<>();

public Console(TextArea ta) {
this.output = ta;
out = System.out;
}

@Override
public void write(int i) throws IOException {
Platform.runLater(() -> {
bytes.add((byte)i);

byte[] array = new byte[bytes.size()];
int q = 0;
for (Byte current : bytes) {
array[q] = current;
q++;
}
try {
output.setText(new String(array, "UTF-8"));
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
out.write(i);
});


}

}

更新2

经过一些优化,这就是我最终得到的代码。

//Cut all the imports
public class LogScreen {

private static TextArea textArea = new TextArea();
private static List<Byte> bytes = new ArrayList<>();
//And some other unnecessary variables

public static void show() {
update();
logStage.showAndWait();

}

public static void init() {
//Cut window initialization
PrintStream ps = new PrintStream(new Console(), true);
System.setOut(ps);
System.setErr(ps);
}

public static void update() {
byte[] array = new byte[bytes.size()];
int q = 0;
for (Byte current : bytes) {
array[q] = current;
q++;
}
try {
textArea.setText(new String(array, "UTF-8"));
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
}

public static class Console extends OutputStream {
private PrintStream out;

public Console() {
out = System.out;
}

@Override
public void write(int i) throws IOException {
Platform.runLater(() -> {
bytes.add((byte)i);
out.write(i);
if (logStage.isShowing()) {
update();
}
});
}

@Override
public void write(byte[] i) {
Platform.runLater(() -> {
for (byte b : i) {
bytes.add(b);
out.write(b);
}
if (logStage.isShowing()) {
update();
}
});
}
}
}

最佳答案

它不能这样工作。

来自 OutputStream.write(int) 的 javadoc

Writes the specified byte to this output stream. The general contract for write is that one
byte is written to the output stream. The byte to be written is the eight low-order bits
of the argument b. The 24 high-order bits of b are ignored.

这意味着对于由两个字节组成的任何字符(例如 П - 0xD0、0x9F),此方法将被调用两次。但是,如果您使用 PrintStream.print(String.valueOf((char) i)) ,您将根据默认编码创建基于这些单字节的字符。这会导致您的示例出现乱码输出。

您应该使用out.write(int),而不是使用out.print(..),它在字节级别而不是字符上写入。

以下代码片段将预期输出打印到控制台。

static class Console extends OutputStream {
private PrintStream out;

public Console() {
out = System.out;
}

@Override
public void write(int i) throws IOException {
out.write(i);
}
}

public static void main(String[] args) throws Exception {
Console console = new Console();
PrintStream ps = new PrintStream(console, true);
System.setOut(ps);
System.setErr(ps);
ps.println("Привет, мир!");
}

关于java - 创建正确处理两字节字符的自定义 OutputStream,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33628536/

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