
![]() |
Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
|
ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
[216.73.216.198] |
![]() |
|
Сообщ.
#1
,
|
|
|
Делаю простую задачу: читаю в консоли клавишу с помощью метода ReadKey() и добавляю
полученный символ в строковую переменную. Вот код: ![]() ![]() ConsoleKeyInfo keyInfo = new ConsoleKeyInfo(); string str = null; while (true) { keyInfo = Console.ReadKey(); if (keyInfo.Key == ConsoleKey.Enter) break; str += keyInfo.KeyChar; } Console.WriteLine("\n{0}",str); С латинскими символами проблем нет, а вместо русских - выдает знаки вопроса и при вводе и при выводе. В чем дело не могу понять. Попытки подключить кодовую страницу: Console.OutputEncoding = Encoding.GetEncoding(1251); или получить строку из набора байт, соответствующих введенным символам: string res = Encoding.GetEncoding(1251).GetString(Encoding.Default.GetBytes(str.ToCharArray())); ни к чему хорошему не приводят. Помогите, пожалуйста! |
Сообщ.
#2
,
|
|
|
Цитата avt @ Делаю простую задачу: читаю в консоли клавишу с помощью метода ReadKey() и добавляю полученный символ в строковую переменную. Вот код: ![]() ![]() ConsoleKeyInfo keyInfo = new ConsoleKeyInfo(); string str = null; while (true) { keyInfo = Console.ReadKey(); if (keyInfo.Key == ConsoleKey.Enter) break; str += keyInfo.KeyChar; } Console.WriteLine("\n{0}",str); С латинскими символами проблем нет, а вместо русских - выдает знаки вопроса и при вводе и при выводе. В чем дело не могу понять. Попытки подключить кодовую страницу: Console.OutputEncoding = Encoding.GetEncoding(1251); или получить строку из набора байт, соответствующих введенным символам: string res = Encoding.GetEncoding(1251).GetString(Encoding.Default.GetBytes(str.ToCharArray())); ни к чему хорошему не приводят. Помогите, пожалуйста! У меня твой код работает отлично, попробуй использовать "Cyrillic (DOS)" 866 вместо 1251 |
Сообщ.
#3
,
|
|
|
Что значит попробовать кириллицу Dos?
Console.OutputEncoding = Encoding.GetEncoding(866); не помогает Напиши, какой должен быть код! |
Сообщ.
#4
,
|
|
|
Цитата avt @ Попытки подключить кодовую страницу: Console.OutputEncoding = Encoding.GetEncoding(1251); У твоей консоли просто нет такой кодировочной страницы наверное. Посмотри какие есть варианты кодировок командой chcp с командной строки. |
Сообщ.
#5
,
|
|
|
Цитата avt @ Что значит попробовать кириллицу Dos? Console.OutputEncoding = Encoding.GetEncoding(866); не помогает Напиши, какой должен быть код! Твой код работает! Сделай то что посоветовал Vladimir У меня в консоли пишет ![]() ![]() C:\>chcp Текущая кодовая страница: 866 C:\> Добавлено И с русскими буквами проблем нет. |
Сообщ.
#6
,
|
|
|
![]() ![]() string cyrillic = "У твоей консоли просто нет такой кодировочной страницы наверное. "; string utf8 = Encoding.UTF8.GetString(Encoding.UTF8.GetBytes(cyrillic)); Console.OutputEncoding = Encoding.UTF8; Console.WriteLine(utf8); Console.Read(); При условии что в консоле выбраны Lucida Console получается вроде нормально. Добавлено Ну как, вывелась строка? ![]() Добавлено Цитата Coffee @ У меня твой код работает отлично, попробуй использовать "Cyrillic (DOS)" 866 вместо 1251 У тебя Default кодировка наверное сразу на кириллице стоит, а у avt на какой-то другой. Гляди, байты беруться с Default кодировкой, а строка потом читается с 1251. Могут быть проблемы. ![]() ![]() string res = Encoding.GetEncoding(1251).GetString(Encoding.Default.GetBytes(str.ToCharArray())); |
Сообщ.
#7
,
|
|
|
Работа со строками в разных кодировках в C#
может поможет |
Сообщ.
#8
,
|
|
|
Так тоже должно работать:
![]() ![]() string res = Encoding.GetEncoding(1251).GetString(Encoding.GetEncoding(1251).GetBytes(cyrillic.ToCharArray())); |
Сообщ.
#9
,
|
|
|
На команду чеккодпэйдж командная строка выдала ..866.
строки типа Console.WriteLine("Привет") работают нормально. метод ReadLine() тоже работает прекрасно. А строка с методом GetString не идет... Отробатывая пошагово, смотрю за переменными _key и _keyChar (они в keyInfo). Если, например, нажать в русской раскладке клавишу G(П), то в _key попадает символ G а в _keyChar - какой-то непонятный символ, напоминающий Y с кодом 1199. Таким образом, Метод ReadKey() уже при чтении клавиши выдаёт знак вопроса вместо русского символа (т.е. дает ошибку на входе). И вот еще что: если в моем коде вместо строки str += keyInfo.KeyChar; написать строку str += keyInfo.Key; то и с латиницей начинаются проблемы: ввожу строку в нижнем регистре, а выводятся - те же символы, но напечатанные заглавными буквами. Т.е. свойство Key дает ошибку на выходе. Я пробовал: мой код на другом компьютере (Visual C# 2010 Express) работает замечательно без всяких кодировок. Но как только вместо KeyChar взять Char, начинаются чудеса. Добавлено Ошибка в предыдущем сообщении: "Но как только вместо KeyChar взять |
Сообщ.
#10
,
|
|
|
Цитата avt @ А строка с методом GetString не идет... Там у тебя в исходной строке по ходу уже не кириллица а неизвестные знаки. ![]() Добавлено Цитата avt @ Т.е. свойство Key дает ошибку на выходе. Не, он же представляет клавишу. Она называется G. Если б у тебя было ДВЕ клавиши - одна для G, а другая для g, тогда б они по разному бы обозначались. Добавлено Цитата avt @ в _keyChar - какой-то непонятный символ, напоминающий Y с кодом 1199. Таким образом, Метод ReadKey() уже при чтении клавиши выдаёт знак вопроса вместо русского символа (т.е. дает ошибку на входе). Какие-то проблемы с чтением кодировки unicode |
Сообщ.
#11
,
|
|
|
Я согласен, в keyInfo.Key читаются клавиши а не символы, и никакой ошибки на выходе не существует!
Остается понять, что с Unicode-ом |
Сообщ.
#12
,
|
|
|
Пробую смотреть, какие коды соответствуют введенным символам.
После цикла while добавляю следующий код: ![]() ![]() int cp = 65001; // 65001 это юникод utf-8 char[] ch = str.ToCharArray(); byte[] b = Encoding.GetEncoding(cp).GetBytes(ch); for (int i = 0; i < b.Length; i++) Console.Write(b[i] + " "); Ввожу 'абв' - на выходе должно быть 208 176 208 177 и 208 178, а у меня 210 160 210 161 210 162. Если брать cp=1200 (utf-16), то должно быть 48 4 49 4 50 4, а у меня 160 4 161 4 162 4, что соответствует последовательности 'абв' в кодировке 866, если брать 0, 2 и 4 элементы массива b. Того же эффекта можно добиться и при cp = 65001, если брать 1, 3 и 6 элементы этого массива. ![]() ![]() char[] ch = str.ToCharArray(); byte[] b = Encoding.GetEncoding(1200).GetBytes(ch); for (int i = 0; i < b.Length; i++) Console.Write(b[i] + " "); byte[] b1 = new byte[b.Length / 2]; for (int i = 0; i < b1.Length; i++) b1[i] = b[i * 2]; Console.WriteLine("\n{0}",Encoding.GetEncoding(866).GetString(b1)); Те, у кого такая проблема, это поймут... Но это не решение вопроса. Остается непонятным, почему в VS Team System 2008 имеется такая чехорда с кодировками. Может быть, это глюк Net framework 3.5 и его просто надо заменить на новый?.. Вопрос остается открытым! |
Сообщ.
#13
,
|
|
|
Цитата avt @ Если брать cp=1200 (utf-16), то должно быть 48 4 49 4 50 4, а у меня 160 4 161 4 162 4, что соответствует Что то вы путаете. У юникода нулевая страница содержит символы ASCII. потому совершенно ожиданно, что UTF16 переведёт "abc" в "61 00 62 00 63 00". Данный код у меня так и работает: ![]() ![]() var enc = System.Text.Encoding.GetEncoding(1200); var txt = "abc"; var b1 = enc.GetBytes(txt); var b2 = Encoding.Unicode.GetBytes(txt); Whhops! язык перепутал. у вас же абв. щас... ![]() Добавлено для "абв" данный код даёт так же ожиданный результат "30 04 31 04 32 04" (HEX), что соответствует, например, этой информации: http://ru.wikipedia.org/wiki/Windows-1251 - там в табличке подписаны номера юникода для символов этой кодировки. Добавлено Если у вас не такой результат - вероятно у вас в системе почему то неверно получается кодировка по её коду. Наведите в дебаге на полученую кодировку по коду 1200 и убедитесь что её имя - EncodingName = "Unicode" или WebName = "utf-16". |
Сообщ.
#14
,
|
|
|
Программное решение исходного вопроса следующее:
![]() ![]() ConsoleKeyInfo keyInfo = new ConsoleKeyInfo(); string str = null; while (true) { keyInfo = Console.ReadKey(); if (keyInfo.Key == ConsoleKey.Enter) break; str += keyInfo.KeyChar; } char[] ch = str.ToCharArray(); byte[] b = Encoding.GetEncoding(1200).GetBytes(ch); byte[] b1 = new byte[b.Length / 2]; for (int i = 0; i < b1.Length; i++) b1[i] = b[i * 2]; string str2 = Encoding.GetEncoding(866).GetString(b1); и в str2 попадают корректные символы, которые можно анализировать на предмет совпадения с эталоном. Тот факт, что при вводе остаются знаки вопроса, для меня не важно, так как я их маскирую звездочками (изначально решается задача входа в некую среду по паролю). Другой вопрос, почему у одних все работает нормально (например, в 2010-ом экспрессе), а у других (в 2005 и 2008-ой студии) - нет, и как данную проблему решить не программно, а системно (чтобы всё у всех работало правильно). Я пробовал переустановить net framework на более позднюю версию, - не помогает. |