\u0413\u0443\u0441\u0435\u043D\u0438\u0446\u0430

Apr 23, 2010 16:12

Эх, засорять ЖЖ никому не нужным кодом - так засорять! :)

Вот читаешь книжки - в них все понятно, особенно когда одно из другого вытекает, примеры все простые и красивые...
А как встает конкретная задача - голову-то и поломаешь...

В общем, задача: хочу я из строки, которая в заголовке, получить нормальную человеческую строку, которая будет понятна обычному русскому человеку, который читать умеет.

Чтобы не было, как в анекдоте:

Приходит программист к окулисту. Тот его
усаживает напротив таблицы, берет указку:
- Читайте!
- "БНОПНЯ"... Доктор, у вас что-то не то
с кодировкой!


1. Определимся, что это Unicode, и что это русские буквы (0×0410 - 0×044F).

В моей задаче в подобных строках могут быть только русские буквы, поэтому через несколько часов не очень активного осмысления (с учетом того что на работе, все-таки), проб и нескончаемых ошибок в результате, начала я уже приходить к тому, чтобы просто написать свой "переводчик". Тем более, что пишется-то он не долго.

(На всякий случай, таблицу с кодами для кириллицы можно посмотреть тут, к примеру: http://isms.ru/art/ris/6.gif)

Но это же .NET!
С ним не может быть как с пациентом в анекдоте

Окулист и пациент:
- Прочтите эту строчку!
- Не могу.
- Да у вас близорукость!
- Блин! Мало того, что я неграмотный, так ещё и близорукий!

Нет, может, конечно, но не в этом случае - тут он должен быть грамотным. По крайней мере, мне так казалось, и именно поэтому я не сдавалась. Тем более не хотелось писать свой велосипед :)

2. Был среди возможных решений вариант декодировать строку при помощи HttpServerUtility.UrlDecode() и у меня, и не только у меня - не помогло.

В .NET Framework есть класс System.Text.Encoding, который позволяет переводить строку из одной кодировки в другую.
На это-то и попала я и мои знакомые, с которыми я советовалась.

Проблема в том, что сама эта строка - она уже имеет кодировку Unicode. Пихать ее кодировщику нет никакого смысла. Но это до меня сегодня уже только дошло :)
*да, мозги задеревенели совсем, каюсь*

3. Ну, а тут уже все проще - вычленить из этой строки 16-ричные числа, и получить их символьное представление :)

string sucode = sourcetextBox.Text.Substring(1,sourcetextBox.Text.Length-1);
//sucode = "\u0413\u0443\u0441\u0435\u043D\u0438\u0446\u0430"

string[] suarr = sucode.Split('\\');
for (int i = 0; i < suarr.Length; i++)
{
    int ic = Convert.ToInt32(suarr[i].Replace("u",""), 16);
    string sc = Char.ConvertFromUtf32(ic); //или char cc = (char)ic; результат тот же

ResultTextBox.AppendText(sc);
}

Его еще допричесывать немного, но и так результат будет уже правильный.

Итак, правильный ответ: Гусеница :)

Upd: слегка причесанный вариант - используя регулярные выражения:

Regex RE = new Regex(@"\u(?(\d|[a-f]){4})", RegexOptions.Multiline);
Match M = RE.Match(sourcetextBox.Text);

while (M.Success)
{
    foreach (Capture C in M.Groups["code"].Captures)
    {
        int ic = Convert.ToInt32(C.Value, 16);
        string sc = Char.ConvertFromUtf32(ic);
        ResultTextBox.AppendText(sc.ToString());
    }
    M = M.NextMatch();
}

Плюс этого решения - строки могу содержать пробелы, точки и запятые, а регулярное выражение выцепит только 16-ричные числа. В первом варианте можно решить с помощью стека, например (ну как числовые выражения со скобками вычисляются).
Упс, собрать бы итоговую строку тоже с этими пробелами и знаками - ну это заменой можно, тем же RegEx.

программерское

Previous post Next post
Up