将文本从UTF-8转换为Windows 1251

时间:2015-07-06 08:01:59

标签: delphi delphi-xe8

我尝试将utf8中的文本转换为windows1251。

这是源文本Ñàíêò-Ïåòåðáóðã 这是目标Санкт-Петербург

我测试了很多功能:Utf8ToAnsi,UTF8ToString,Utf8Encode等但是没有得到真正的结果。

需要帮助。

2 个答案:

答案 0 :(得分:6)

让我们试着猜猜你在问什么。看看前五个字符:

Ñàíêò

如果我们假设它们实际上来自8 bit Windows code page 1252,那么在十六进制中它们就像这样编码:

D1 E0 ED EA F2

现在,解释为8 bit Windows code page 1251时的那五个字节是:

Санкт

所以似乎这里没有涉及UTF-8。您只是将文本误解为来自代码页1252,而实际上它来自1251。

  

我测试了很多功能:Utf8ToAnsi,UTF8ToString,Utf8Encode等,但没有得到真实的结果。

更一般地说,当你发现自己随意调用函数时,通常这意味着你还没有完全理解这个问题。能够识别这种感觉是一种有用的技能,并且知道是时候退后一步并尝试获得更深入的理解。

对于解释如何从UTF-8转换为1251的人来说,没有太多意义,因为那不是你需要做的。我不会试图向您展示任何解决问题的代码,因为我不知道:

  1. 数据来自哪里,或
  2. 您需要将数据转换为何种形式。
  3. 很可能你已经将这些字节读入AnsiString代码页1252.但是在这一点上,我判断猜测是一个太过分的步骤。如果您在问题中添加一些说明,那么我们可以添加更多详细信息。

答案 1 :(得分:0)

  

我尝试将utf8中的文本转换为windows1251。

由于您使用的是Delphi 2009+,最简单的解决方案是使用UT8StringAnsiString(N)类型,让RTL为您处理转换(除非您正在为移动平台进行编译,其中如果没有安装third party compiler patch),则无法使用案例UTF8StringAnsiString(N)

type
  Win1251String = type AnsiString(1251);
var
  Utf8: UTF8String;
  Win1251: Win1251String;
begin
  // populate UTF-8 as needed...
  Utf8 := ...;

  // converts from UTF-8 to UTF-16 to Windows-1251...
  Win1251 := Win1251String(Utf8);

  // use Win1251 as needed...
end;

或者,您可以使用RTL的UnicodeFromLocaleChars()LocaleCharsFromUnicode()函数:

var
  Utf8: UTF8String;
  Utf16: UnicodeString;
  Win1251: RawByteString;
begin
  // populate UTF-8 as needed...
  Utf8 := ...;

  // convert from UTF-8 to UTF-16...
  SetLength(Utf16, UnicodeFromLocaleChars(65001, 0, PAnsiChar(UTf8), Length(Utf8), nil, 0));
  UnicodeFromLocaleChars(65001, 0, PAnsiChar(Utf8), Length(Utf8), PWideChar(Utf16), Length(Utf16));

  // convert from UTF-16 to Windows-1251...
  SetLength(Win1251, LocaleCharsFromUnicode(1251, 0, PWideChar(Utf16), Length(Utf16), nil, 0, nil, nil));
  LocaleCharsFromUnicode(1251, 0, PWideChar(Utf16), Length(Utf16), PAnsiChar(Win1251), Length(Win1251), nil, nil);
  SetCodePage(Win1251, 1251);

  // use Win1251 as needed...
end;

或者您可以直接使用Win32 MultiByteToWideChar()WideCharToMultiByte()函数(或第三方Unicode库,例如iconv或ICU):

var
  Utf8: UTF8String;
  Utf16: UnicodeString; // or WideString in pre-2009 versions
  Win1251: AnsiString;
begin
  // populate UTF-8 as needed...
  Utf8 := ...;

  // convert from UTF-8 to UTF-16...
  SetLength(Utf16, MultiByteToWideChar(65001, 0, PAnsiChar(UTf8), Length(Utf8), nil, 0));
  MultiByteToWideChar(65001, 0, PAnsiChar(Utf8), Length(Utf8), PWideChar(Utf16), Length(Utf16));

  // convert from UTF-16 to Windows-1251...
  SetLength(Win1251, WideCharToMultiByte(1251, 0, PWideChar(Utf16), Length(Utf16), nil, 0, nil, nil));
  WideCharToMultiByte(1251, 0, PWideChar(Utf16), Length(Utf16), PAnsiChar(Win1251), Length(Win1251), nil, nil);

  // use Win1251 as needed...
end;
  

这是源文本Ñàíêò-Ïåòåðáóðã这是目标Санкт-Петербург

Ñàíêò-Ïåòåðáóðã不是Санкт-Петербург的UTF-8编码形式,正确的UTF-8编码形式将是Санкт-Петербург。因此,正如其他人所指出的那样,您的数据实际上并不是以UTF-8开头编码的。

  

我测试了很多功能:Utf8ToAnsi,UTF8ToString,Utf8Encode等但是没有得到真正的结果。

Utf8ToAnsi()不允许您指定目标字符集。在Delphi 2009+中,它将UTF-8字符串解码为UTF-16 UnicodeString。在2009年之前的版本中,它解码为AnsiString,使用操作系统默认的Ansi代码页进行编码,无论发生什么情况。

UTF8ToString()将UTF-8字符串解码为UTF-16 UnicodeString

Utf8Encode()将UTF-16 WideString / UnicodeString编码为UTF-8。