2014-09-27 50 views
2

這是我的代碼:如何讓System.in輸入流讀取utf-8字符?

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 
Ä 
ğ 

如何查看正確的字母而不是Ä?掃描儀似乎做正確的事情。

實際上,爲什麼這種方法不起作用?這裏有什麼問題?

回答

2

InputStream包裝在InputStreamReader中。

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

如果有必要,你可以通過一個特定的Charset讀者的構造,但默認情況下,它將只使用默認的字符集,這可能是正確的。

+0

那麼,但爲什麼我的方法不工作?我試圖學習更多,而不是試圖讓它工作。 – 2014-09-27 17:22:58

+2

@KorayTugay因爲無論編碼如何,InputStream#read都讀取一個字節。在UTF-8中,「»是一個多字節字符,因此您的方法只是讀取第一個字節並顯示其ASCII值。閱讀器將正確讀取兩個字節以創建適當的字符。 – 2014-09-27 17:24:21

3

的Javadoc InputStream#read()狀態

中讀取數據的從輸入流的下一個字節。

但事實證明,字符ğ需要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編碼字符只需要一個字節來表示,所以如果您知道需要多少字節,您應該只做我們剛纔所做的。否則,讀取所有內容並將其傳遞給解碼器。

+0

謝謝,像往常一樣很好的答案。 – 2014-09-27 17:29:57

3

InputStream.read() retruns數據的下一個byte,這是一個數字0到255之間

在這裏,你只是轉換是bytechar,而你的情況給Ä

Scanner另一方面,讀取整個字符串,這就是爲什麼你看到它正確輸出。我建議你使用掃描儀,而不是簡單的InputStream,因爲它提供了便捷的閱讀文本的方法。