You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何正确转换UTF-8缓冲区与Delphi普通字符串?解决尾零问题

Delphi无管理UTF-8缓冲区转换后出现尾随零的解决方法

问题描述

我按照Delphi官方建议编写了代码片段,无编译警告或隐式转换,但结果不符合预期。代码如下:

procedure Convert;
type
  TUTF8Buf = array [0 .. 5] of byte;
var
  s: string;
  sutf8: UTF8String; // 可管理的UTF-8字符串
  utf8str: TUTF8Buf; // 无管理缓冲区
begin
  utf8str := Default (TUTF8Buf); // utf8str = (0,0,0,0,0,0)
  s := UTF8ArrayToString(utf8str); // s = #0#0#0#0#0#0
  s := 'abc'; // s = 'abc'
  sutf8 := UTF8Encode(s); // sutf8 = 'abc'
  Move(sutf8[1], utf8str[0], Min(Length(sutf8), sizeof(utf8str) - 1)); // utf8str = (97, 98, 99, 0, 0)
  s := UTF8ArrayToString(utf8str); // s = 'abc'#0#0#0
  s := UTF8ToString(sutf8); // s = 'abc'
end;

使用可管理UTF-8字符串时运行正常,但使用无管理缓冲区时总会产生尾随零。请问处理此类缓冲区的现代正确方法是什么?

核心原因

UTF8ArrayToString会处理数组的全部字节,包括缓冲区中未被覆盖的尾随零。无管理缓冲区不像UTF8String那样自带长度标识,转换时必须明确指定有效数据的范围,而非让函数处理整个数组。

现代处理方法

方法一:使用带长度参数的UTF8ToString重载

从Delphi 10.3开始,System.SysUtils提供了接受字节指针和有效长度的UTF8ToString重载,直接转换缓冲区的有效部分:

procedure Convert;
type
  TUTF8Buf = array [0 .. 5] of byte;
var
  s: string;
  sutf8: UTF8String;
  utf8str: TUTF8Buf;
  validLen: Integer;
begin
  s := 'abc';
  sutf8 := UTF8Encode(s);
  validLen := Min(Length(sutf8), SizeOf(utf8str));
  Move(sutf8[1], utf8str[0], validLen);
  // 传入缓冲区指针和有效长度进行转换
  s := UTF8ToString(@utf8str[0], validLen); // 结果为'abc',无尾随零
end;

方法二:构造临时UTF8String(兼容旧版本)

如果你的Delphi版本不支持上述重载,可将缓冲区有效数据复制到临时UTF8String后再转换:

procedure Convert;
type
  TUTF8Buf = array [0 .. 5] of byte;
var
  s: string;
  sutf8: UTF8String;
  utf8str: TUTF8Buf;
  tempUTF8: UTF8String;
  validLen: Integer;
begin
  s := 'abc';
  sutf8 := UTF8Encode(s);
  validLen := Min(Length(sutf8), SizeOf(utf8str));
  Move(sutf8[1], utf8str[0], validLen);
  // 构造仅包含有效数据的UTF8String
  SetLength(tempUTF8, validLen);
  if validLen > 0 then
    Move(utf8str[0], tempUTF8[1], validLen);
  s := UTF8ToString(tempUTF8); // 结果为'abc',无尾随零
end;

关键注意事项

  • 不要依赖零作为终止符:UTF-8编码允许包含零字节(如编码U+0000),用零判断结束会导致错误,必须始终跟踪有效数据长度。
  • 缓冲区大小计算:无需刻意预留终止符位置,直接使用实际有效长度即可,带长度的转换函数不需要依赖终止符。

内容的提问来源于stack exchange,提问作者Molochnik

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.12 04:20:35