8

如何将 WideString(或其他长字符串)转换为 UTF-8 中的字节数组?

4

6 回答 6

13

像这样的功能将满足您的需求:

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;
于 2011-03-08T14:20:08.400 回答
9

您可以TEncoding.UTF8.GetBytes在 SysUtils.pas中使用

于 2011-03-08T14:53:15.577 回答
5

如果您使用的是 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 并直接转到字节数组;只需将返回类型更改为TBytesor array of Byte。(如果您希望数组以空值结尾,您可能还希望将长度增加一。SetLength 将对字符串隐式执行此操作,但对数组执行此操作。)

如果您有一些其他字符串类型既不是 WideString、UnicodeString 也不是 UTF8String,那么将其转换为 UTF-8 的方法是先将其转换为 WideString 或 UnicodeString,然后再将其转换回 UTF-8。

于 2011-03-08T15:01:39.880 回答
4
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 只会使样本更难阅读。

于 2011-03-08T14:09:54.053 回答
1

我有以下两个例程(源代码可以在这里下载 - http://www.csinnovations.com/framework_utilities.htm):

函数 CsiBytesToStr(const pInData: TByteDynArray; pStringEncoding: TECsiStringEncoding; pIncludesBom: Boolean): 字符串;

函数 CsiStrToBytes(const pInStr: string; pStringEncoding: TECsiStringEncoding; pIncludeBom: Boolean): TByteDynArray;

于 2011-03-08T23:51:15.307 回答
1

宽字符串-> 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 的评论。

于 2011-03-09T12:57:05.793 回答