我目前的logClass有一个问题,无法打印umlauts“üäß”,我创建这个命令是为了将控制台上的每个字符串打印到JTextPane。
我已经在方法“控制台”上将PrintStream设置为使用“UTF-8”,并且我已经尝试了不同的字体,但是在尝试打印特殊字符时,我总是会出现错误字符。有人会对如何解决这个问题提出建议吗?
这是我的代码:
private JPanel logPanel;
private JScrollPane logScrollPanel;
private JTextPane textArea;
private Thread stdOutReader;
private Thread stdErrReader;
private boolean stopThreads;
private final PipedInputStream stdOutPin = new PipedInputStream();
private final PipedInputStream stdErrPin = new PipedInputStream();
private StyledDocument doc;
private Style style;
public void Console() {
doc = (StyledDocument) textArea.getDocument();
style = doc.addStyle("ConsoleStyle", null);
StyleConstants.setFontFamily(style, "MonoSpaced");
StyleConstants.setFontSize(style, 12);
try {
PipedOutputStream stdOutPos = new PipedOutputStream(this.stdOutPin);
System.setOut(new PrintStream(stdOutPos, true, "UTF-8"));
} catch (java.io.IOException io) {
textArea.setText("Couldn't redirect STDOUT to this console\n" + io.getMessage());
} catch (SecurityException se) {
textArea.setText("Couldn't redirect STDOUT to this console\n" + se.getMessage());
}
try {
PipedOutputStream stdErrPos = new PipedOutputStream(this.stdErrPin);
System.setErr(new PrintStream(stdErrPos, true, "UTF-8"));
} catch (java.io.IOException io) {
textArea.setText("Couldn't redirect STDERR to this console\n" + io.getMessage());
} catch (SecurityException se) {
textArea.setText("Couldn't redirect STDERR to this console\n" + se.getMessage());
}
stopThreads = false;
stdOutReader = new Thread(this);
stdOutReader.setDaemon(true);
stdOutReader.start();
stdErrReader = new Thread(this);
stdErrReader.setDaemon(true);
stdErrReader.start();
}
public synchronized void run() {
try {
while (Thread.currentThread() == stdOutReader) {
try {
this.wait(100);
} catch (InterruptedException ie) {
}
if (stdOutPin.available() != 0) {
String input = this.readLine(stdOutPin);
StyleConstants.setForeground(style, Color.black);
doc.insertString(doc.getLength(), input, style);
textArea.setCaretPosition(textArea.getDocument().getLength());
}
if (stopThreads) {
return;
}
}
while (Thread.currentThread() == stdErrReader) {
try {
this.wait(100);
} catch (InterruptedException ie) {
}
if (stdErrPin.available() != 0) {
String input = this.readLine(stdErrPin);
StyleConstants.setForeground(style, Color.red);
doc.insertString(doc.getLength(), input, style);
textArea.setCaretPosition(textArea.getDocument().getLength());
}
if (stopThreads) {
return;
}
}
} catch (Exception e) {
textArea.setText("\nConsole reports an Internal error.");
textArea.setText("The error is: " + e);
}
}
private synchronized String readLine(PipedInputStream in) throws IOException {
String input = "";
do {
int available = in.available();
if (available == 0) {
break;
}
byte b[] = new byte[available];
in.read(b);
input += new String(b, 0, b.length);
} while (!input.endsWith("\n") && !input.endsWith("\r\n") && !stopThreads);
return input;
}
System.setout(新的打印流(标准输出,真,“UTF-8”));
这是不正确的。
"System out"不是"屏幕",而是一个抽象的概念:它是java应用程序的"标准out"。那是什么?嗯,你不知道。如果你的应用程序是用java-jar启动的myapp.jar
至关重要的是,“标准输出”,即抽象,从根本上说是基于字节的,而不是基于char的。因此,它是一个
输出流
(或者更确切地说,一个打印流,它只是一个比扎罗输出流)。不是写入器
(写入器是输出流的字符变体)。
那么,当您只运行
java-jarmyapp.jar
,而不运行时,它是如何工作的呢?
嗯,你输入命令的shell会告诉操作系统启动应用程序,这样标准输出要么直接连接回shell,然后以某种方式处理它,要么将它连接到它本身当前也连接到的“控制台设备”。
从那里,java应用程序发送的字节(不是字符!请记住,它是基于字节的!)由该shell或tty处理。发送字节65,然后出现一个
A
。
至关重要的是,shell/tty正在查看字节并必须将它们转换为字符。它的做法与所有将字节转换为字符或反之亦然的事情相同:使用字符集编码。
你必须回答的问题是:什么是字符集编码?-这是你必须指定的字符集编码,而不是UTF-8。因为将其设置为UTF_8意味着你写入打印流的字符通过UTF-8编码变成字节。如果tty使用CP1252将字节解码回字符,除了ASCII字符之外的所有内容都将变成mojibake。
除了java.nio.file中的内容外,java17之前的Javas将默认大多数字节到字符转换器。文件
类转换为“平台本地编码”,通常您写入的tty使用的是平台本地编码。这意味着,在java17之前,您需要编写:System。setOut(new PrintStream(stdOutPos,true))
,它就可以工作了。
但是,从java17(还是java18?)开始,一切都默认为UTF-8。因此,您必须编写这个残暴的灾难:
Charset nativeCharset = Charset.forName(System.getProperty("native.encoding", Charset.defaultEncoding().name());
Scanner sc = new Scanner(System.in, nativeCharset);
PrintStream out = new PrintStream(System.out, true, nativeCharset);
要求native.encoding属性是唯一的方法,但是在java17之前,系统属性不存在,所以我们必须回退到默认值(defaultEncode()从java17及更高版本一直是UTF-8,但它是java16及更早版本中的本机编码)。
如果这仍然不起作用,让你的tty告诉它它在字符集编码中使用什么,然后在你的java代码中也应用它。你怎么做?这取决于你使用的tty。在linux上,通常只是:键入
set
,点击回车键,然后检查各种环境变量,其中一个会提到它。
更复杂的是,通常当您在IDE中运行应用程序时,它们使用自己的字符集编码(通常是UTF-8),即使系统编码是其他编码
native。据我所知,编码
并不能解决问题。
解决所有这些问题的策略是使用控制台(
System.getConsole()
),但如果目标是让应用程序也能在IDE中执行,那么所有IDE……都无法实现它。
从本质上讲,从java应用程序将非ASCII写入控制台现在是一场灾难。
我正在使用dbf数据库和亚美尼亚字母,DBF编码是未知的,所以我创建了一个字母映射来解码复活的字符串。现在我有一个有效的Unicode字符串,但由于这个错误,我无法打印出来: UnicodeEncode 错误: “charmap” 编解码器无法对位置 0-5 中的字符进行编码:字符映射到 到目前为止我所尝试的: 怎么修
问题内容: 我正在使用BeautifulSoup从HTML提取一些文本,但是我只是想不出如何正确地将其打印到屏幕(或与此相关的文件)上。 这是我的包含文本的类的样子: 当尝试打印一个实例时,这是我在控制台上看到的: 无论我尝试什么,都无法获得想要的输出(上面的文本应该是希伯来语)。我的最终目标是序列化到文件(使用json或pickle)并能够将其读回。 我在Ubuntu 10.10上使用Pytho
问题内容: 这肯定是一件容易的事,但这确实困扰着我。 我有一个脚本,可以读取网页并使用Beautiful Soup对其 进行解析。我从 汤中 提取所有链接,因为我的最终目标是打印出link.contents。 我要解析的所有文本都是ASCII。我知道Python将字符串视为unicode,并且我确信这非常方便,在我的wee脚本中没有用。 每次我去打印一个包含’String’的变量时,我都会被打印到
我想正确打印unicode(比如希腊字符),但我有问题。例如: 问题是是否有任何解决方案可以正确打印所有卡哈拉特。我认为对于希腊字符,UTF-16是可以的。
问题内容: 我有一个已编码为UTF-8的俄语字符串 当我在Eclipse控制台中打印字符串时,我得到有人可以建议如何将俄语字符串打印到控制台,或者我在这里做错了什么? 我尝试过使用它将其转换为字节,然后仍然是同样的问题:-( 问题答案: 试试这个: 或这个: 俄语的主要问题是正确设置UTF-8编码。
#include <stdio.h> #include <wchar.h> int main(void) { char str1[] = "abcd"; wchar_t str2[] = L"abcd"; return 0; } 技巧 用gdb调试程序时,可以使用“x/s”命令打印ASCII字符串。以上面程序为例: Temporary brea