gpt4 book ai didi

Java 标准输入编码 Windows cmd、Netbeans

转载 作者:行者123 更新时间:2023-11-30 05:46:14 25 4
gpt4 key购买 nike

如您所知, InputStreamReader 将阅读提供的InputStream并将其字节解码为字符。如果没有charset指定后,它将使用默认字符集

我们可以使用 java.nio.charset.Charset.defaultCharset().displayName() 检查这个默认字符集 .

情况 1。我的 Windows CMD 使用 cp850 ,但 Java 报告 windows-1252 。可以证明输入字符óSystem.in.read()将报告162 ,正如预期的那样。 InputStreamReader但是,将无法解码它,因为它预计运行 windows-1252 ,显示¢ (这是第 162 个 windows-1252 字符)。

情况 2。在 Windows 中,我的 Netbeans 集成终端使用 windows-1252 ,但 Java 报告 UTF-8 。同样,可以证明输入字符 óSystem.in.read()将报告243 ,正如预期的那样。 InputStreamReader但是,将无法解码它,因为它预计运行 UTF-8 ,显示 (代码65533)。

情况 3。我的 Debian 机器使用 UTF-8无处不在,在 GNOME 和 Netbeans 终端中。当输入字符ó时, System.in.read()将报告两个字节,195161 ,对应于UTF-8该字符的表示。 InputStreamReader将显示ó正如预期的那样。

我想要什么?有没有办法正确检测使用的实际字符集,以便我可以从命令行读取字符(在 Windows CMD 和 Windows 中的 Netbeans 中)没有什么特殊情况吗?

非常感谢。

B 计划:案例 2 可以通过 changing Netbeans file encoding to UTF-8 解决(它也将处理 UTF-8 文件,这是 IDE 在 2019 年应该做的事情)。情况 1 可以通过将代码页更改为 UTF-8 来解决,但我无法做到这一点。

您可以使用以下程序来测试这些情况。输入相同的字符两次并比较输出。

import java.io.*;
import java.nio.charset.Charset;

public class Prova2 {
public static void main(String[] args) throws Exception {
int b;

System.out.println("Charset.defaultCharset: " + Charset.defaultCharset().displayName());
System.out.println("I will read the next bytes: ");
while ((b = System.in.read()) != '\n') {
System.out.println("I have read this byte: " + b + " (" + (char) b + ")");
}
System.out.println("I will read the next chars: ");
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
while ((b = br.read()) != '\n') {
System.out.println("I have read this char: " + b + " (" + (char) b + ")");
}
System.out.println("Thank you.");
}

}

最佳答案

Is there a way to correctly detect the actual charset used so I can read characters from the command line without any special case?

在 Windows 上您可以 detect (or even set) the code page used从命令行读取字符时 using JNA 。但是,如果使用替代方法来获取控制台输入,则没有必要:

  • 不要从 System.in 读取数据,而是使用 System.console 捕获用户输入。这允许将提交的文本作为String而不是bytechar进行处理。它提供对所有 String 方法的访问,以将控制台输入解释为字节、字符或 UTF-8 数据。
  • 使用这种方法时,在从命令行提交输入之前设置合适的代码页至关重要。例如,如果提交俄语字符,则使用 chcp 1251 将代码页设置为 1251。

使用这种方法只需两行代码即可获取用户输入:

Console console = System.console();
String userInput = console.readLine();

Case 2. In Windows, my Netbeans integrated terminal uses windows-1252...

不要浪费时间尝试让控制台输入在 NetBeans 中正常工作。 System.console() 将返回 null,并且无法配置其控制台。我怀疑其他 IDE 中也存在类似的限制。无论如何,NetBeans 内的测试不会带来任何有意义的好处。只需专注于从命令行进行测试。

Case 2 can be solved by changing Netbeans file encoding to UTF-8...

使用下面的方法,项目的编码设置并不重要。无论编码设置为 Windows-1252 还是 UTF-8,它都会起作用。

注释:

  • 我只在 Windows 上进行了测试,但只要控制台环境设置正确,代码就应该可以在其他平台上运行。 (据我所知,使用 chcp 是 Windows 特有的。)
  • 和您一样,我无法让 chcp 65001 用于 Unicode 输入。只需专注于确保可以使用合适的代码页成功读取输入即可。例如,当使用 OP 中提到的字符(ócent)进行测试时,使用支持这两个字符的任何代码页都可以。例如:437、850、1252 等。如果应用程序正确显示提交的字符,那么一切都会好起来的(反之亦然)。

这是代码,主要包括显示控制台输入:

package prova3;

import java.io.Console;
import java.io.UnsupportedEncodingException;
import java.nio.charset.StandardCharsets;
import java.util.stream.Collectors;

public class Prova3 {

public static void main(String[] args) throws UnsupportedEncodingException {

Console console = System.console();
if (console == null) {
System.out.println("System.console() return null.");
System.out.println("If you are trying to run from within your IDE, use the command line instead.");
return;
}
System.out.println("Enter some characters...");
String userInput = console.readLine();
System.out.println("User input: " + userInput + " [String length: " + userInput.length() + ", chars: " + userInput.toCharArray().length + ", bytes: " + userInput.getBytes(StandardCharsets.UTF_8).length + "]");
System.out.println("codepoints: " + userInput.codePoints().boxed().map(n -> "x" + Integer.toHexString(n) + " (" + n + ")").collect(Collectors.toList()).toString());
System.out.println("UTF-8 bytes: " + getBytesList(userInput));
}

static String getBytesList(String userInput) throws UnsupportedEncodingException {
StringBuilder byteList = new StringBuilder("[");
for (int i = 0; i < userInput.length(); i++) {
byte[] bytes = userInput.substring(i, i + 1).getBytes(StandardCharsets.UTF_8);
for (int j = 0; j < bytes.length; j++) {
byteList.append(Character.forDigit((bytes[j] >> 4) & 0xF, 16))
.append(Character.forDigit((bytes[j] & 0xF), 16));
if (j < bytes.length - 1) {
byteList.append(" ");
}
}
if (i < userInput.length() - 1) {
byteList.append(", ");
}
}
byteList.append("]");
return byteList.toString();
}
}

chcp

关于Java 标准输入编码 Windows cmd、Netbeans,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54794272/

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