Есть ли способ перевести текст из Unicode в ASCII? - PullRequest
1 голос
/ 13 апреля 2011

Для каждого символа ASCII мне нужно что-то вроде списка эквивалентных символов Unicode.

Проблема в том, что такие программы, как Microsoft Excel и Word, вставляют двойные кавычки без ASCII, одинарные кавычки, тире и т. Д., Когда люди вводят документы. Я хочу сохранить этот текст в поле базы данных типа "varchar", для которого требуются однобайтовые символы.

Для хранения ASCII (однобайтового) текста некоторые из этих символов Unicode можно считать эквивалентными или достаточно схожими с конкретным символом ASCII, который подойдет для замены символа Unicode эквивалентным символом ASCII.

Мне нужна простая функция, такая как MapToASCII, которая преобразует текст Unicode в эквивалент ASCII, позволяя мне указать символ замены для любых символов Unicode, которые не похожи на символы ASCII.

Ответы [ 2 ]

1 голос
/ 13 апреля 2011

Win32 API WideCharToMultiByte может использоваться для этого преобразования (Unicode в ANSI). Используйте CP_ACP в качестве первого параметра. Нечто подобное, вероятно, будет лучше, чем попытка создать собственную функцию отображения.

Редактировать С риском, что я пытаюсь выдвинуть это как решение вопреки желаниям ОП, может показаться, что стоит отметить, что этот API делает многое (все?) Из чего просят. Цель состоит в том, чтобы отобразить (я думаю) строку Юникода как можно больше в «ANSI» (где ANSI может быть чем-то вроде движущейся цели в этом случае). Дополнительным требованием является возможность указать альтернативный символ для тех, которые не могут быть отображены. Следующий пример делает это. Он «преобразует» строку Unicode в char и использует подчеркивание (от второго до последнего параметра) для тех символов, которые не могут быть преобразованы.

ret = WideCharToMultiByte( CP_ACP, 0, L"abc個חあЖdef", -1, 
                           ac, sizeof( ac ), "_", NULL );
for ( i = 0; i < strlen( ac ); i++ )
  printf( "%c %02x\n", ac[i], ac[i] );
0 голосов
/ 14 апреля 2011

Здесь очень актуальный вопрос: Замена знаков препинания в Юникоде ASCII-аппроксимациями

Хотя ответа здесь недостаточно, это дало мне идею. Я мог бы сопоставить каждую из кодовых точек Unicode в Базовой многоязычной плоскости (0) с эквивалентным символом ASCII, если таковой существует. Следующий код C # поможет создать HTML-форму, в которой вы можете ввести символ замены для каждого значения.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Globalization;
using System.IO;

namespace UnicodeCharacterCategorizer
{
    class Program
    {
        static void Main(string[] args)
        {
            string output_filename = "output.htm"; //set a filename if not specifying one through the command line
            Dictionary<UnicodeCategory,List<char>> category_character_sets = new Dictionary<UnicodeCategory,List<char>>();
            foreach (UnicodeCategory c in Enum.GetValues(typeof(UnicodeCategory)))
                category_character_sets.Add( c, new List<char>() );
            for (int i = 0; i <= 0xFFFF; i++)
            {
                if (i >= 0xD800 && i <= 0xDFFF) continue; //Skip ranges reserved for high/low surrogate pairs.
                char c = (char)i;
                UnicodeCategory category = char.GetUnicodeCategory( c );
                category_character_sets[category].Add( c );
            }
            StringBuilder file_data = new StringBuilder( @"<!DOCTYPE html PUBLIC ""-//W3C//DTD XHTML 1.0 Transitional//EN"" ""http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd""><html xmlns=""http://www.w3.org/1999/xhtml""><head><title>Unicode Category Character Sets</title><style>.categoryblock{border:3px solid black;margin-bottom:10px;padding:5px;} .characterblock{display:inline-block;border:1px solid grey;padding:5px;margin-right:5px;} .character{display:inline-block;font-weight:bold;background-color:#ffeeee} .numericvalue{color:blue;}</style></head><body><form id=""charactermap"">" );
            foreach (KeyValuePair<UnicodeCategory,List<char>> entry in category_character_sets)
            {
                file_data.Append( @"<div class=""categoryblock""><h1>" + entry.Key.ToString() + ":</h1><br />" );
                foreach (char c in entry.Value)
                {
                    string hex_value = ((int)c).ToString( "x" );
                    file_data.Append( @"<div class=""characterblock""><span class=""character"">&#x" + hex_value + @";<br /><span class=""numericvalue"">" + hex_value + @"</span><br /><input type=""text"" name=""r_" + hex_value + @""" /></div>" );
                }
                file_data.Append( "</div>" );
            }
            file_data.Append("</form></body></html>" );
            File.WriteAllText( output_filename, file_data.ToString(), Encoding.Unicode );
        }
    }
}

В частности, этот код будет генерировать HTML-форму, содержащую все символы в BMP вместе с входными текстовыми полями, названными в честь шестнадцатеричных значений с префиксом «r_» (r означает «значение замены»). Если это перенести на страницу ASP.NET, можно было бы написать дополнительный код, чтобы максимально заполнить значения замены:

  • со своим собственным значением, если уже ASCII, или
  • с нормализованными Unicode FormD или разложенными эквивалентами FormKD, или
  • одно значение ASCII для всей категории (т. Е. Все символы «начальная пунктуация» с двойной кавычкой ASCII)

Затем вы можете пройти вручную и внести коррективы, и это, вероятно, не займет так много времени, как вы думаете. Есть только 64512 кодовых точек, и большие куски целых категорий, вероятно, могут быть отклонены как «нет даже близко к чему-либо ASCII». Итак, я собираюсь построить эту карту и функционировать.

...