Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/mercurial/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
UTF-8中的字符串到字节数组?_Utf 8_Lazarus_Freepascal - Fatal编程技术网

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. 根据所需字节的用途,可能需要包含空终止符 对于生产代码,请确

如何在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.
根据所需字节的用途,可能需要包含空终止符


对于生产代码,请确保测试空字符串。添加所需的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以生成其结果。