Преобразование символов Hi-Ansi в эквивалент Ascii (é -> e)
-
19-09-2019 - |
Вопрос
Есть ли в Delphi 2007 процедура для преобразования символов в верхнем диапазоне таблицы ANSI (> 127) в их эквивалентные символы в чистом ASCII (<= 127) в соответствии с языковым стандартом (кодовой страницей)?
Я знаю, что некоторые символы не могут быть хорошо переведены, но большинство может, особенно.в диапазоне 192-255:
- À → А
- à → а
- Ë → Э
- ë → е
- Ç → С
- ç → с
- – (тире) → - (дефис – это может быть сложнее)
- — (эм тире) → - (дефис)
Решение
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;
Вызов этого с вашими примерами дает результаты, которые вы ищете, включая случай с тире в минус, который, я не думаю, обрабатывается предложением Джеруна о преобразовании в форму нормализации D.Если вы действительно хотите использовать этот подход, у Майкла Каплана есть Сообщение блога в нем явно обсуждается удаление диакритических знаков (а не нормализация в целом), но используется C# и API, представленный в Vista.Вы можете получить нечто подобное, используя API FoldString (любая версия WinNT).
Конечно, если вы делаете это только для одного набора символов и хотите избежать накладных расходов на преобразование в WideString и обратно, Паду прав, что простой цикл for и таблица поиска будут столь же эффективны.
Другие советы
Просто чтобы расширить ответ Крейга для 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 внутри Windows использует WideCharToMultiByte, тогда как на Mac используется iconv (см. LocaleCharsFromUnicode в System.pas).Вопрос в том, следует ли рассматривать это различное поведение в разных ОС как ошибку и сообщать об этом в CodeCentral.
Я считаю, что лучше всего создать таблицу поиска.
То, что вы ищете, это нормализация.
Майкл Каплан написал хорошая статья в блоге о нормализации.
Это не решит вашу проблему сразу, но укажет вам правильное направление.
--джероен