【问题标题】:How can I make System.in Input Stream read utf-8 characters?如何让 System.in 输入流读取 utf-8 字符?
【发布时间】:2014-09-27 17:14:33
【问题描述】:

这是我的代码:

public class MyTestClass {
    public static void main(String[] args) throws Exception {
        Scanner scanner = new Scanner(System.in);
        String s = scanner.nextLine();
        InputStream inputStream = System.in;
        int read = inputStream.read();
        System.out.println(read);
        System.out.println((char)read);
        System.out.println(s);
    }
}

我在运行程序时输入了两次字母ğ。控制台输出将是:

ğ
ğ
196
Ä
ğ

我如何才能看到正确的字母而不是 Ä?扫描仪似乎做对了。

实际上,为什么这种方法不起作用?这里有什么问题?

【问题讨论】:

    标签: java encoding


    【解决方案1】:

    InputStream#read() 状态的 javadoc

    从输入流中读取数据的下一个字节。

    但事实证明,字符 ğ 需要 2 个字节来表示 UTF-8。因此,您需要读取两个字节。你可以使用InputStream#read(byte[])

    byte[] buffer = new byte[2];
    inputStream.read(buffer);
    

    一旦字节数组包含适当的字节,您需要以 UTF-8 对它们进行解码。你可以这样做

    char val = StandardCharsets.UTF_8.decode(ByteBuffer.wrap(buffer)).get();
    

    变量val 现在将包含解码后的字符。

    请注意,一些 UTF-8 编码的字符只需要一个字节来表示,所以如果你知道你需要多少字节,你应该只做我们刚才做的事情。否则,读取所有内容并将其传递给解码器。

    【讨论】:

      【解决方案2】:

      InputStream.read() 重新运行下一个 byte 数据,它是一个介于 0 和 255 之间的数字。

      在这里,您只是将 byte 转换为 char,在您的情况下,这将得到 Ä

      Scanner 另一方面,读取整个字符串,这就是你看到它正确输出的原因。我建议你使用 Scanner 而不是普通的InputStream,因为它提供了方便的阅读文本的方法。

      【讨论】:

        【解决方案3】:

        InputStream 包装在InputStreamReader 中。

        int read = new InputStreamReader(System.in).read();
        System.out.println((char) read); // prints 'ğ'
        

        如有必要,您可以将特定的Charset 传递给阅读器的构造函数,但默认情况下,它只会使用默认字符集,这可能是正确的。

        【讨论】:

        • 好吧,但为什么我的方法不起作用?我正在努力学习而不是让它发挥作用。
        • @KorayTugay 因为InputStream#read 读取单个字节,无论编码如何。 ğ 在 UTF-8 中是一个多字节字符,因此您的方法只读取第一个字节并显示其 ASCII 值。阅读器将正确读取两个字节以创建正确的字符。
        猜你喜欢
        • 2017-04-06
        • 1970-01-01
        • 2015-07-26
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2010-10-29
        • 1970-01-01
        相关资源
        最近更新 更多