2009-07-23 52 views
1

另一個問題重新。 Unicode,終端,現在C#和wc。如果我寫這個簡單的代碼TextWriter.ReadToEnd與Unix wc命令

int i=0; 
    foreach(char c in Console.In.ReadToEnd()) 
    { 
    if(c!='\n') i++; 
    } 
    Console.WriteLine("{0}", i); 

並將其輸入只有字符「€」(3個字節以UTF-8),wc返回3個字符(可能使用所述wint_t,雖然我還沒有檢查),但ReadToEnd()返回1(一個字符)。在這種情況下,ReadToEnd的行爲究竟是什麼?我怎麼知道ReadToEnd在幕後做了些什麼?

我正在運行xterm,使用utf-8.en.US進行初始化,運行Ubuntu Linux和Mono。

謝謝。

回答

3

wc和大多數類似unix的命令處理字符的數據類型通常是一個無符號的8位整數。 wc只是從標準輸入中逐個讀取字節,不進行轉換,並確定有3個字符。

.NET根據自己的Char數據類型處理字符,該數據類型是一個16位無符號整數並表示UTF-16字符。控制檯類已收到3個字節的輸入,確定它所連接的控制檯是UTF-8,並已正確將它們轉換爲單個UTF-16歐元字符。

+0

所以,快速跟進問題。如果我要用C編寫相同的程序,通過使用wchar或wint_t,我會浪費(兩次)空間。在這種情況下,它是微不足道的,因爲它只是16位,但在巨大的文件中,差異是顯而易見的。它是否正確? – 2009-07-23 03:08:06

2

ReadToEnd返回一個字符串。 .NET中的所有字符串都是Unicode。它們不僅僅是一個字節數組。

顯然,wc正在返回字節數。字節的數量和字符的數量曾經是相同的東西。

3

您需要考慮字符編碼。目前,您只是計算字節數,並且char s和byte s不一定是相同的大小。

Encoding encoding = Encoding.UTF8; 
string s = "€"; 

int byteCount = encoding.GetByteCount(s); 
Console.WriteLine(byteCount); // prints "3" on the console 

byte[] bytes = new byte[byteCount]; 
encoding.GetBytes(s, 0, s.Length, bytes, 0); 
int charCount = encoding.GetCharCount(bytes); 
Console.WriteLine(charCount); // prints "1" on the console 
1

wc,默認情況下,返回一個文件的行,字和字節數。如果要根據活動語言環境的編碼返回字符數,而不是僅返回字節數,則應查看現代wc所具有的-m--chars選項。