Чтение unicode с консоли
Я пытаюсь прочитать строку unicode из консоли в С#, для примера, позволяет использовать его:
C:\SVN\D³ebugger\SRC\виталик\Program.cs
Сначала я просто попытался Console.ReadLine()
, который вернул мне c:\SVN\D3ebugger\src\???????\Program.cs
Я попытался установить Console.InputEncoding в UTF8, как и 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, чтобы он разбился на ВСЕ исключение (включая собственные), но приложение все равно потерпит крах.
Я также нашел эту открытую ошибку в Microsoft Connect, которая, похоже, говорит, что сейчас невозможно прочитать Unicode из консоли InputStream.
Стоит отметить, хотя и не строго связанный с моим вопросом, что Console.WriteLine умеет правильно печатать эту строку, если для Console.OutputEncoding установлено значение UTF8.
Спасибо!
Обновление 1
Я ищу решение для .NET 3.5
Обновление 2
Обновлен с полным кодом, который я использовал.
Ответы
Ответ 1
Здесь одна полностью работающая версия в .NET 3.5 Client:
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]()
Ответ 2
Кажется, что это прекрасно работает при настройке клиентского профиля .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]()