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。

我相信你最好的选择是创建一个查找表。

您正在寻找的是标准化。

迈克尔·卡普兰写了一篇 关于标准化的好博客文章.

它不会立即解决您的问题,但会为您指明正确的方向。

——杰罗恩

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top