如何将 WideString(或其他长字符串)转换为 UTF-8 中的字节数组?
6 回答
像这样的功能将满足您的需求:
function UTF8Bytes(const s: UTF8String): TBytes;
begin
Assert(StringElementSize(s)=1);
SetLength(Result, Length(s));
if Length(Result)>0 then
Move(s[1], Result[0], Length(s));
end;
您可以使用任何类型的字符串调用它,RTL 将从传递给 UTF-8 的字符串编码转换。所以不要被欺骗认为在调用之前必须转换为 UTF-8,只需传入任何字符串并让 RTL 完成工作。
之后,它是一个相当标准的数组副本。请注意显式调用 UTF-8 编码字符串的字符串元素大小假设的断言。
如果你想得到零终结符,你可以这样写:
function UTF8Bytes(const s: UTF8String): TBytes;
begin
Assert(StringElementSize(s)=1);
SetLength(Result, Length(s)+1);
if Length(Result)>0 then
Move(s[1], Result[0], Length(s));
Result[high(Result)] := 0;
end;
您可以TEncoding.UTF8.GetBytes
在 SysUtils.pas中使用
如果您使用的是 Delphi 2009 或更高版本(Unicode 版本),将 WideString 转换为 UTF8String 是一个简单的赋值语句:
var
ws: WideString;
u8s: UTF8String;
u8s := ws;
编译器将调用正确的库函数进行转换,因为它知道 UTF8String 类型的值具有CP_UTF8
.
在 Delphi 7 及更高版本中,您可以使用提供的库函数Utf8Encode
。对于更早的版本,您可以从其他库(例如 JCL)中获取该函数。
您还可以使用 Windows API 编写自己的转换函数:
function CustomUtf8Encode(const ws: WideString): UTF8String;
var
n: Integer;
begin
n := WideCharToMultiByte(cp_UTF8, 0, PWideChar(ws), Length(ws), nil, 0, nil, nil);
Win32Check(n <> 0);
SetLength(Result, n);
n := WideCharToMultiByte(cp_UTF8, 0, PWideChar(ws), Length(ws), PAnsiChar(Result), n, nil, nil);
Win32Check(n = Length(Result));
end;
很多时候,您可以简单地使用 UTF8String 作为数组,但如果您真的需要字节数组,您可以使用 David 和 Cosmin 的函数。如果您正在编写自己的字符转换函数,则可以跳过 UTF8String 并直接转到字节数组;只需将返回类型更改为TBytes
or array of Byte
。(如果您希望数组以空值结尾,您可能还希望将长度增加一。SetLength 将对字符串隐式执行此操作,但对数组执行此操作。)
如果您有一些其他字符串类型既不是 WideString、UnicodeString 也不是 UTF8String,那么将其转换为 UTF-8 的方法是先将其转换为 WideString 或 UnicodeString,然后再将其转换回 UTF-8。
var S: UTF8String;
B: TBytes;
begin
S := 'Șase sași în șase saci';
SetLength(B, Length(S)); // Length(s) = 26 for this 22 char string.
CopyMemory(@B[0], @S[1], Length(S));
end.
根据您需要字节的用途,您可能需要包含一个 NULL 终止符。
对于生产代码,请确保您测试空字符串。添加所需的 3-4 LOC 只会使样本更难阅读。
我有以下两个例程(源代码可以在这里下载 - http://www.csinnovations.com/framework_utilities.htm):
函数 CsiBytesToStr(const pInData: TByteDynArray; pStringEncoding: TECsiStringEncoding; pIncludesBom: Boolean): 字符串;
函数 CsiStrToBytes(const pInStr: string; pStringEncoding: TECsiStringEncoding; pIncludeBom: Boolean): TByteDynArray;
宽字符串-> UTF8:
http://www.freepascal.org/docs-html/rtl/system/utf8decode.html
相反:
http://www.freepascal.org/docs-html/rtl/system/utf8encode.html
请注意,在 D2009 之前的系统(包括当前的 Free Pascal)中将宽字符串分配给 ansistring 将转换为本地 ansi 编码,出现乱码。
对于 TBytes 部分,请参见上面 Rob Kennedy 的评论。