22

Есть ли доступная в Delphi 2007 программа для преобразования символов в большом диапазоне таблицы ANSI (> 127) в их эквивалентные в чистом ASCII (< = 127) согласно языку (кодовой странице)?Преобразование символов Hi-Ansi в эквивалент Ascii (é -> e)

Я знаю, что некоторые символы не могут хорошо перевести, но большинство может, особенно. в диапазоне 192-255:

  • ÀA
  • à
  • ËЕ
  • Мобайле
  • БЗС
  • çс
  • -(ен тире)-(дефис - что может быть сложнее)
  • -(em dash)-(дефис)

ответ

27

WideCharToMultiByte делает наиболее подходящее отображение для любых символов, которые не поддерживается указанным набором символов, в том числе вскрышных диакритиков. Вы можете сделать именно то, что хотите, используя это и пропустив 20127 (US-ASCII) в качестве кодовой страницы.

function BestFit(const AInput: AnsiString): AnsiString; 
const 
    CodePage = 20127; //20127 = us-ascii 
var 
    WS: WideString; 
begin 
    WS := WideString(AInput); 
    SetLength(Result, WideCharToMultiByte(CodePage, 0, PWideChar(WS), 
    Length(WS), nil, 0, nil, nil)); 
    WideCharToMultiByte(CodePage, 0, PWideChar(WS), Length(WS), 
    PAnsiChar(Result), Length(Result), nil, nil); 
end; 

procedure TForm1.Button1Click(Sender: TObject); 
begin 
    ShowMessage(BestFit('aÀàËëÇç–—€¢Š')); 
end; 

Calling, что с примерами дает результаты, которые вы ищете, включая случай emdash-к-минус, который я не думаю, что обрабатывается предложение Jeroen, чтобы преобразовать в нормализации формы D. Если вы сделали хочу воспользоваться этим подходом, у Майкла Каплана есть blog post, в котором явно обсуждаются дезапиляционные диакритики (а не нормализация вообще), но он использует C# и API, который вводится в Vista. Вы можете получить что-то подобное, используя FoldString api (любой выпуск WinNT).

Конечно, если вы делаете это только для одного набора символов, и вы хотите избежать накладных расходов от преобразования в WideString и из него, Padu правильно, что простой цикл и таблица поиска будут столь же эффективны ,

+0

Спасибо Крэйг. Это более общее решение, чем поиск. У него была опечатка в магическом числе, поэтому я исправил ее и использовал вместо нее константу. Но в любом случае, он работает на D2007, а также на D2009. –

+0

Одна вещь, которую мы заметили с этим, заключается в том, что 'β' (unicode 1E9E latin заглавная буква sharp s) не преобразуется, поэтому мы делаем это заранее: StringReplace (aStr, 'β', 'SS', [rfReplaceAll]) – PatrickvL

3

Я считаю, что вам лучше всего создает таблицу поиска.

+0

Кроме того, если вы используете приличную библиотеку регулярных выражений с delphi, это также можно использовать, но она по-прежнему выглядит как таблица поиска. –

+0

Спасибо Паду. Это то, о чем я думал. Я все же соглашусь ответить Крейг, потому что это более общий. –

1

Что вы ищете, это нормализация.

Michael Kaplan написал nice blog article about normalization.

Он не сразу решает вашу проблему, но указывает на то, что вы в правильном направлении.

--jeroen

+1

NFKD + удаление комбинирующих меток работает много времени. Тем не менее, есть такие символы, как 'ÆÐØÞßæðøþ', которые не разлагаются и должны обрабатываться вручную. – dan04

7

Просто продлить ответ Крейга на Delphi 2009:

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

function OStripAccents(const aStr: String): String; 
type 
    USASCIIString = type AnsiString(20127);//20127 = us ascii 
begin 
    Result := String(USASCIIString(aStr)); 
end; 

К сожалению, этот код работает только на MS Windows. На Mac акценты не заменяются лучшими персонажами, а вопросительными знаками.

Очевидно, что Delphi внутренне использует WideCharToMultiByte в Windows, тогда как на Mac iconv используется (см. LocaleCharsFromUnicode в System.pas). Вопрос в том, следует ли рассматривать это поведение в разных ОС как ошибку и сообщать CodeCentral.

+0

iconv имеет параметр '// TRANSLIT', но' LocaleCharsFromUnicode() 'не использует его. –

Смежные вопросы