有没有办法从字符串中获取 ANSI 字符?当字符串包含表情符号时 Utf8decode 失败
Is there a way to get just the ANSI characters from a string? Utf8decode fails when string contains emojis
首先,我从 HTTP 请求中获取了一个 TMemoryStream,其中包含响应的主体。
然后我将它加载到 TStringList 中并将文本保存在宽字符串中(也尝试使用 ansistring)。
问题是我需要转换字符串,因为用户语言是西班牙语,所以带重音符号的元音很常见,我需要存储信息。
lServerResponse := TStringList.Create;
lServerResponse.LoadFromStream(lResponseMemoryStream);
lStringResponse := lServerResponse.Text;
lDecodedResponse := Utf8Decode(lStringResponse );
如果响应(其中一部分)是“Hólá Múndó”,lStringResponse 值将为“Hólá Mãºndó”,lDecodedResponse 将为“Hólá Múndó”。
但是如果用户添加任何表情符号(如果表情符号是 ,lStringResponse 值将是“Hólá Múndó ðŸ∼€”)Utf8Decode 失败并且 returns 一个空字符串。
有没有办法只从字符串(或 MemoryStream)中获取 ANSI 字符?或者删除任何 Utf8Decode 无法转换的字符?
谢谢你的时间。
TMemoryStream
只是原始字节。没有理由将该流加载到 TStringList
中只是为了从中提取 (Wide|Ansi)String
。您可以使用 SetString()
将字节直接分配给 AnsiString
/UTF8String
,例如:
var
lStringResponse: UTF8String;
lDecodedResponse: WideString;
begin
SetString(lStringResponse, PAnsiChar(lResponseMemoryStream.Memory), lResponseMemoryStream.Size);
lDecodedResponse := UTF8Decode(lStringResponse);
end;
只要确保 HTTP 内容确实编码为 UTF-8,否则此方法将不起作用。
也就是说 - Delphi 中的 UTF8Decode()
(和 UTF8Encode()
)7 不 支持 U+FFFF 以上的 Unicode 代码点,这意味着他们根本不支持表情符号。该问题已在 Delphi 2009 年修复。
要在早期版本中解决该问题,您可以改用 Win32 API MultiByteToWideChar()
函数,例如:
uses
..., Windows;
function My_UTF8Decode(const S: UTF8String): WideString;
var
WLen: Integer;
begin
WLen := MultiByteToWideChar(CP_UTF8, 0, PAnsiChar(S), Length(S), nil, 0);
if WLen > 0 then
begin
SetLength(Result, WLen);
MultiByteToWideChar(CP_UTF8, 0, PAnsiChar(S), Length(S), PWideChar(Result), WLen);
end else
Result := '';
end;
var
lStringResponse: UTF8String;
lDecodedResponse: WideString;
begin
SetString(lStringResponse, PAnsiChar(lResponseMemoryStream.Memory), lResponseMemoryStream.Size);
lDecodedResponse := My_UTF8Decode(lStringResponse);
end;
或者:
uses
..., Windows;
function My_UTF8Decode(const S: PAnsiChar; const SLen: Integer): WideString;
var
WLen: Integer;
begin
WLen := MultiByteToWideChar(CP_UTF8, 0, S, SLen, nil, 0);
if WLen > 0 then
begin
SetLength(Result, WLen);
MultiByteToWideChar(CP_UTF8, 0, S, SLen, PWideChar(Result), WLen);
end else
Result := '';
end;
var
lDecodedResponse: WideString;
begin
lDecodedResponse := My_UTF8Decode(PAnsiChar(lResponseMemoryStream.Memory), lResponseMemoryStream.Size);
end;
首先,我从 HTTP 请求中获取了一个 TMemoryStream,其中包含响应的主体。 然后我将它加载到 TStringList 中并将文本保存在宽字符串中(也尝试使用 ansistring)。
问题是我需要转换字符串,因为用户语言是西班牙语,所以带重音符号的元音很常见,我需要存储信息。
lServerResponse := TStringList.Create;
lServerResponse.LoadFromStream(lResponseMemoryStream);
lStringResponse := lServerResponse.Text;
lDecodedResponse := Utf8Decode(lStringResponse );
如果响应(其中一部分)是“Hólá Múndó”,lStringResponse 值将为“Hólá Mãºndó”,lDecodedResponse 将为“Hólá Múndó”。
但是如果用户添加任何表情符号(如果表情符号是 ,lStringResponse 值将是“Hólá Múndó ðŸ∼€”)Utf8Decode 失败并且 returns 一个空字符串。 有没有办法只从字符串(或 MemoryStream)中获取 ANSI 字符?或者删除任何 Utf8Decode 无法转换的字符?
谢谢你的时间。
TMemoryStream
只是原始字节。没有理由将该流加载到 TStringList
中只是为了从中提取 (Wide|Ansi)String
。您可以使用 SetString()
将字节直接分配给 AnsiString
/UTF8String
,例如:
var
lStringResponse: UTF8String;
lDecodedResponse: WideString;
begin
SetString(lStringResponse, PAnsiChar(lResponseMemoryStream.Memory), lResponseMemoryStream.Size);
lDecodedResponse := UTF8Decode(lStringResponse);
end;
只要确保 HTTP 内容确实编码为 UTF-8,否则此方法将不起作用。
也就是说 - Delphi 中的 UTF8Decode()
(和 UTF8Encode()
)7 不 支持 U+FFFF 以上的 Unicode 代码点,这意味着他们根本不支持表情符号。该问题已在 Delphi 2009 年修复。
要在早期版本中解决该问题,您可以改用 Win32 API MultiByteToWideChar()
函数,例如:
uses
..., Windows;
function My_UTF8Decode(const S: UTF8String): WideString;
var
WLen: Integer;
begin
WLen := MultiByteToWideChar(CP_UTF8, 0, PAnsiChar(S), Length(S), nil, 0);
if WLen > 0 then
begin
SetLength(Result, WLen);
MultiByteToWideChar(CP_UTF8, 0, PAnsiChar(S), Length(S), PWideChar(Result), WLen);
end else
Result := '';
end;
var
lStringResponse: UTF8String;
lDecodedResponse: WideString;
begin
SetString(lStringResponse, PAnsiChar(lResponseMemoryStream.Memory), lResponseMemoryStream.Size);
lDecodedResponse := My_UTF8Decode(lStringResponse);
end;
或者:
uses
..., Windows;
function My_UTF8Decode(const S: PAnsiChar; const SLen: Integer): WideString;
var
WLen: Integer;
begin
WLen := MultiByteToWideChar(CP_UTF8, 0, S, SLen, nil, 0);
if WLen > 0 then
begin
SetLength(Result, WLen);
MultiByteToWideChar(CP_UTF8, 0, S, SLen, PWideChar(Result), WLen);
end else
Result := '';
end;
var
lDecodedResponse: WideString;
begin
lDecodedResponse := My_UTF8Decode(PAnsiChar(lResponseMemoryStream.Memory), lResponseMemoryStream.Size);
end;