2012-02-29 189 views
12

我想從C#控制檯讀取unicode字符串,例如着想讀unicode的,讓他USET一個:從控制檯

C:\ SVN \D³ebugger的\ src \виталик\的Program.cs

起初我只是試圖Console.ReadLine()這回我c:\SVN\D3ebugger\src\???????\Program.cs

我已經盡力了Console.InputEncoding設置爲UTF-8,像這樣Console.InputEncoding = Encoding.UTF8但回到我c:\SVN\D³ebugger\src\???????\Program.cs,基本上打亂字符串的西里爾部分。

所以隨機磕磕絆絆我試圖設置這樣的編碼,Console.InputEncoding = Encoding.GetEncoding(1251);其中返回c:\SVN\D?ebugger\src\виталик\Program.cs,這次會破壞³字符。

在這一點上,似乎通過切換encodings爲InputStream我一次只能得到一種語言。

我也試着去本地,做這樣的事情:

// Code 
public static string ReadLine() 
{ 
    const uint nNumberOfCharsToRead = 1024; 
    StringBuilder buffer = new StringBuilder(); 

    uint charsRead = 0; 
    bool result = ReadConsoleW(GetStdHandle(STD_INPUT_HANDLE), buffer, nNumberOfCharsToRead, out charsRead, (IntPtr)0); 

    // Return the input minus the newline character 
    if (result && charsRead > 1) return buffer.ToString(0, (int)charsRead - 1); 
    return string.Empty; 
} 

// Extern definitions 

    [DllImport("Kernel32.DLL", ExactSpelling = true)] 
    internal static extern IntPtr GetStdHandle(int nStdHandle); 

    [DllImport("kernel32.dll", CharSet = CharSet.Unicode, ExactSpelling = true)] 
    static extern bool ReadConsoleW(IntPtr hConsoleInput, [Out] StringBuilder lpBuffer, 
     uint nNumberOfCharsToRead, out uint lpNumberOfCharsRead, IntPtr lpReserved); 

,這是工作的罰款對於非Unicode字符串,但是當我試圖使它閱讀我的樣本串,應用程序崩潰。我試圖告訴Visual Studio打破所有異常(包括本機異常),但應用程序仍會崩潰。

我還發現this微軟Connect中的開放性錯誤似乎是說現在從控制檯的InputStream中讀取Unicode是不可能的。

即使與我的問題沒有嚴格關係,值得注意的是,如果Console.OutputEncoding設置爲UTF8,Console.WriteLine能夠打印此字符串就好了。

謝謝!

更新1

我要尋找一個解決方案,.NET 3.5

更新2

與我用全部原生代碼更新。

+0

是否有可能/可以接受的,而不是使用控制檯命名管道? – Goyuix 2012-03-06 02:18:44

+0

如果我沒有找到解決方案,那麼這可能是我會做... – VitalyB 2012-03-06 09:38:20

回答

6

這裏是一個完全正常的版本在.net 3.5客戶端:

class Program 
{ 
    [DllImport("kernel32.dll", SetLastError = true)] 
    static extern IntPtr GetStdHandle(int nStdHandle); 

    [DllImport("kernel32.dll")] 
    static extern bool ReadConsoleW(IntPtr hConsoleInput, [Out] byte[] 
    lpBuffer, uint nNumberOfCharsToRead, out uint lpNumberOfCharsRead, 
    IntPtr lpReserved); 

    public static IntPtr GetWin32InputHandle() 
    { 
    const int STD_INPUT_HANDLE = -10; 
    IntPtr inHandle = GetStdHandle(STD_INPUT_HANDLE); 
    return inHandle; 
    } 

    public static string ReadLine() 
    { 
    const int bufferSize = 1024; 
    var buffer = new byte[bufferSize]; 

    uint charsRead = 0; 

    ReadConsoleW(GetWin32InputHandle(), buffer, bufferSize, out charsRead, (IntPtr)0); 
    // -2 to remove ending \n\r 
    int nc = ((int)charsRead - 2) * 2; 
    var b = new byte[nc]; 
    for (var i = 0; i < nc; i++) 
     b[i] = buffer[i]; 

    var utf8enc = Encoding.UTF8; 
    var unicodeenc = Encoding.Unicode; 
    return utf8enc.GetString(Encoding.Convert(unicodeenc, utf8enc, b)); 
    } 

    static void Main(string[] args) 
    { 
    Console.OutputEncoding = Encoding.UTF8; 
    Console.Write("Input: "); 
    var st = ReadLine(); 
    Console.WriteLine("Output: {0}", st); 
    } 
} 

enter image description here

+0

如果你需要大字符串更改ReadLine()中的bufferSize。請注意緩衝區將**兩次**字符的字節數。另外,如果你不介意使用Linq,你可以使用:var b = buffer.Take(nc).ToArray();而不是那個醜陋的For循環。 – Jcl 2012-03-09 00:34:16

+0

它工作得很好,謝謝!雖然,我做了一些非常相似的事情(使用ReadConsoleW),這根本不起作用。我會檢查我做錯了什麼並更新。 – VitalyB 2012-03-09 14:52:18

+0

之後您可能沒有轉換爲UTF8。可能輸入正常,但輸出不是(只是猜測) – Jcl 2012-03-09 15:54:14

10

這似乎工作正常時,目標.NET 4客戶端配置文件,但不幸的是不是在目標.NET 3.5客戶端配置文件時。確保將控制檯字體更改爲Lucida Console。
正如@jcl指出的那樣,即使我已經瞄準了.NET4,這只是因爲我已經安裝了.NET 4.5。

class Program 
{ 
    private static void Main(string[] args) 
    { 
     Console.InputEncoding = Encoding.Unicode; 
     Console.OutputEncoding = Encoding.Unicode; 

     while (true) 
     { 
      string s = Console.ReadLine(); 

      if (!string.IsNullOrEmpty(s)) 
      { 
       Debug.WriteLine(s); 

       Console.WriteLine(s); 
      } 
     } 
    } 
} 

enter image description here

+0

你是否在.NET 4.5上,也許?它在.NET 4.0中不起作用。行'控制檯。InputEncoding = Encoding.Unicode;'拋出一個異常:「IOException - 參數不正確。」 – VitalyB 2012-03-04 15:48:51

+0

我確實安裝了VS 11 beta和.NET 4.5 beta。但是,控制檯應用程序使用VS 2010和.NET 4客戶端配置文件工作。我正在使用Windows 7 x64 SP1。 – Phil 2012-03-04 15:55:34

+0

我可以確認,當您定位.NET 3.5客戶端配置文件時,我會得到與您相同的異常。 – Phil 2012-03-04 16:08:35