将 Hi-Ansi 字符转换为等效的 Ascii 字符 (é -> e)
-
19-09-2019 - |
题
Delphi 2007 中是否有一个例程可以根据区域设置(代码页)将 ANSI 表高范围 (>127) 中的字符转换为纯 ASCII (<=127) 中的等效字符?
我知道有些字符不能很好地翻译,但大多数可以,尤其是。在 192-255 范围内:
- À → A
- à → A
- Ë → 乙
- ë → e
- Ç → C
- ç → C
- – (破折号) → - (连字符 - 这可能会更棘手)
- — (破折号) → - (连字符)
解决方案
宽字符到多字节 对指定字符集不支持的任何字符进行最佳匹配映射,包括剥离变音符号。您可以使用它并传递 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;
用你的例子调用它会产生你正在寻找的结果,包括 emdash-to-minus 情况,我认为 Jeroen 的建议转换为规范化形式 D 并没有处理这种情况。如果你确实想采取这种方法,迈克尔·卡普兰有一个 博客文章 明确讨论了剥离变音符号(而不是一般的标准化),但它使用 C# 和 Vista 中引入的 API。您可以使用 FoldString api(任何 WinNT 版本)获得类似的东西。
当然,如果您只对一种字符集执行此操作,并且希望避免与 WideString 之间的转换产生的开销,那么 Padu 是正确的,简单的 for 循环和查找表也同样有效。
其他提示
只是为了扩展 Craig 对 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(请参阅 System.pas 中的 LocaleCharsFromUnicode)。问题是不同操作系统上的这种不同行为是否应被视为错误并报告给 CodeCentral。
我相信你最好的选择是创建一个查找表。