【问题标题】:Read and Write UTF-8 characters from System.in stream从 System.in 流中读取和写入 UTF-8 字符
【发布时间】:2017-04-06 20:40:56
【问题描述】:

如果我使用System.out 流的print 方法在控制台上打印像 ελληνικά 这样的 unicode 字符串,它会按预期打印(因为我在支持 UTF 字符的输出控制台中使用 Ubuntu mono )。

但是,如果我尝试使用 System.in 流从带有 UTF-8 编码的控制台 unicode 字符中读取,则无法正确读取。 我已经尝试了许多不同的方法来使用带有 System.in 流的各种阅读器类来实现它,但它从来没有工作过。那么有没有人知道我可以做到这一点的方法

这是一个代码示例

BufferedReader keyboard = new BufferedReader(new InputStreamReader(System.in, "UTF-8"));
BufferedWriter console = new BufferedWriter(new OutputStreamWriter(System.out, "UTF-8"));

console.write("p1: Γίνεται πάντως\n");
console.flush();
System.out.println("p2: Γίνεται πάντως");

byte dataBytes[] = keyboard.readLine().getBytes(Charset.forName("UTF-8"));
System.out.println("p3: " + new String(dataBytes));
console.write("p4: " + new String(dataBytes, "UTF-8") + "\n");
console.flush();
Scanner scan = new Scanner(System.in, "UTF-8");

System.out.println("p5: " + (char) System.in.read());
System.out.println("p6: " + scan.nextLine());
System.out.println("p7: " + keyboard.readLine());

我的控制台上的输出:

p1: Γίνεται πάντως
p2: Γίνεται πάντως
Δέν
p3: ���
p4: ���
Δέν
p5: Ä
p6: ��
Δέν
p7: ���

我的 IDE 是 Netbeans

【问题讨论】:

  • 你能发布你不工作的代码吗?
  • 可能duplicate
  • 我怀疑你的System.in 的编码是UTF-8
  • 如何检查 System.in 的编码?无论如何,系统的属性“file.encoding”是 UTF-8
  • 查看更新的答案。

标签: java input unicode utf-8 inputstream


【解决方案1】:

尝试使用java.io.Console.readLine()java.io.Console.readLine(String, Object...)Console 实例由 System.console() 方法返回。例如:

package package01;

import java.io.Console;

public class Example {

    public static void main(String[] args) {
        Console console = System.console();
        if (console == null) {
            System.err.println("No console");
            System.exit(1);
        }
        String s = console.readLine("Enter string: ");
        System.out.println(s);
    }

}

【讨论】:

  • 使用Console 可能是正确的方法。但是,您应该知道在 IDE 中 System.console() will return null。最好使用Reader 参数创建一个单独的读取方法。然后你可以用System.console().reader() 调用它,或者尝试基于System.in 创建一个阅读器,甚至使用模拟阅读器进行单元测试。
【解决方案2】:

System.in 是一个InputStream,它是一个字节流。您需要Reader 才能读取字符。阅读器将为您进行解码。

在这种情况下,您可以用InputStreamReader 包装System.in,将“UTF-8”作为第二个构造函数参数传递。

Scanner console = new Scanner(new InputStreamReader(System.in, "UTF-8"));
while (console.hasNextLine())
    System.out.println(console.nextLine());

更新:

您的标准输入的编码可能是错误的。为了验证,你可以比较你从System.in得到的字节数组和预期的。

byte [] expected = "Δέν".getBytes("UTF-8"); // [-50, -108, -50, -83, -50, -67]

byte [] fromStdin = new byte[1024];
int c = System.in.read(fromStdin);
for (int i = 0; i < c-1; i++) {
    if (expected[i] != fromStdin[i]) {
        System.out.println(i + ", " + fromStdin[i]);
    }
}

然后输入“Δέν”(不带双引号),然后按 Enter。如果它输出任何内容,则说明您的 System.in 编码错误。

System.in 不应该与defaultCharset 或某些系统属性具有相同的编码吗?

不一定。它是字节流,而不是字符流。它不能是字符流,因为您可以/应该能够提供二进制数据。图像、音频或视频,随心所欲。它必须支持这些。这就是为什么它只是一个InputStream这取决于环境为您的程序提供了什么。而且我对您的环境知之甚少。你需要弄清楚如何改变你的环境,或者弄清楚它实际上给你的程序提供了什么编码。

例如,我们有一个 UTF-16 文本文件 utf16.txt,我们将其内容提供给我们的程序,该程序期望 STDIN 为 UTF-8 编码文本:

java -cp ... our.utf8.Program < utf16.txt

它会读到乱码。

【讨论】:

  • 是的,你是对的。但是如何设置 System.in 的编码?
  • 但是为什么 java.nio.charset.Charset.defaultCharset() 返回“UTF-8”?这不是 System.in 使用的编码吗?
  • 再次更新答案。
  • 所以我看到我必须设置 Windows 环境编码?我该怎么做?
  • 你可以试试this
猜你喜欢
  • 1970-01-01
  • 2015-07-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-06-18
相关资源
最近更新 更多