UTF-8中的字符串到字节数组?
如何在UTF-8中将宽字符串(或其他长字符串)转换为字节数组UTF-8中的字符串到字节数组?,utf-8,lazarus,freepascal,Utf 8,Lazarus,Freepascal,如何在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. 根据所需字节的用途,可能需要包含空终止符 对于生产代码,请确
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.
根据所需字节的用途,可能需要包含空终止符
对于生产代码,请确保测试空字符串。添加所需的3-4 LOC只会使示例更难阅读。这样的函数可以满足您的需要:
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;
如果您使用的是Delphi 2009或更高版本(Unicode版本),则可以在SysUtils.pas中使用
TEncoding.UTF8.GetBytes
,将宽字符串转换为UTF8String是一个简单的赋值语句:
var
ws: WideString;
u8s: UTF8String;
u8s := ws;
编译器将调用正确的库函数进行转换,因为它知道UTF8String类型的值的“代码页”为CP\u UTF8
在Delphi7及更高版本中,您可以使用提供的库函数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;
函数CustomUtf8Encode(const-ws:WideString):UTF8String;
变量
n:整数;
开始
n:=宽图表多字节(cp_UTF8,0,PWideChar(ws),长度(ws),nil,0,nil,nil);
Win32Check(n0);
设置长度(结果,n);
n:=WideCharToMultiByte(cp_UTF8,0,PWideChar(ws),Length(ws),PAnsiChar(Result),n,nil,nil);
Win32Check(n=长度(结果));
结束;
很多时候,您可以简单地使用UTF8String作为数组,但如果您确实需要字节数组,则可以使用David和Cosmin的函数。如果您正在编写自己的字符转换函数,则可以跳过UTF8String并直接转到字节数组;只需将返回类型更改为TBytes
或字节数组
。(如果希望数组以null结尾,也可以将长度增加1。SetLength将隐式地对字符串执行此操作,但对数组执行此操作。)
如果您的其他字符串类型既不是WideString、UnicodeString,也不是UTF8String,那么将其转换为UTF-8的方法是首先将其转换为WideString或UnicodeString,然后将其转换回UTF-8。我有以下两个例程(源代码可以在此处下载-): 函数CsiBytesToStr(const pInData:tbytednarray;pStringEncoding:tecstringencoding;pIncludesBom:Boolean):字符串 函数CsiStrToBytes(const-pInStr:string;pStringEncoding:tecstringencoding; pIncludeBom:Boolean):t字节数组 widestring->UTF8: 相反: 请注意,在D2009之前的系统(包括当前可用的Pascal)中,将宽字符串分配给ansistring将转换为本地ansi编码,即乱码字符
关于T字节部分,请参见上面Rob Kennedy的备注。字符串不是空的。它包含值“ase sașiînșase saci”+1。不是每个人(至少可以这么说!)都知道
Length
函数是如何工作的@Cosmin我可以看到字符串不是空的。我只是有一种感觉,OP可能对文本感兴趣,而不是“ase sașIînșase saci”
@Cosmin,@David:当然@Cosmin是在开玩笑!(大卫的观点确实很好。)我想通过套接字将字节发送到我的Java应用程序。@Cosmin不,不会。这就是断言的意义所在!一个问题。。使用StringElementSize()(lazarus)需要添加什么单位。很抱歉问了这么多问题,我是一个newbie@Mariusz你的“拉撒路”是什么意思?你给问题贴上了标签。在Delphi中,它位于system.pas中,因此所有单元都会自动使用。@Mariusz:您可以删除整个Assert…
行。但是,由于您标记了您的问题Delphi
,而不是free pascal
,@David的答案适用于Delphi,而不是free pascal。但是上面的代码也可以在免费的Pascal中工作。我不知道。试试看。这是D2009+特定的代码,因此在遵循D2009之前语义的FPC上不起作用。将宽字符串(参见原始问题)传递给“UTF8string”会将其更改为本地编码(而不是像D2009+中那样的UTF-8),从而使字符串混乱。FPC对此有专门的文档功能,请参见单独的回答注意,如果输入字符串已编码为UTF-8,GetBytes
将非常浪费。编译器将把输入字符串转换为UnicodeString,因为这是GetBytes
允许的唯一字符串参数,而GetBytes
将把字符转换回UTF-8以生成其结果。