如何将 tencoding 的 getstring 与静态数组的一部分一起使用 w/o 块复制

how to use tencoding's getstring with a part of static array w/o block copying

我正在尝试将 Tencoding.UTF8.Getstring 应用于静态字节数组的一部分,而不将其内容复制到动态数组。如果数组是动态的,我可以使用:

stringvar:=Tencoding.utf8.Getstring(dynbytearray,offset,length);

然而,当我有一个静态的预定义长度数组时,语法不起作用,我所能想到的就是声明一个新的动态数组,设置它的长度,然后复制字节。我不喜欢做不必要的复制,因为我怀疑我只是错过了一个语法技巧。到目前为止,我像 "setlength(newdynarr,whatever); newdynarr:=@staticarr [optional offset]" 这样的尝试都失败了。谢谢

您可以使用 System.UnicodeFromLocaleChars。比如像这样:

uses
  SysUtils, SysConst, Windows;

function Utf8BytesToString(Bytes: PByte; ByteCount: Integer): string;
var
  Len: Integer;
begin
  Len := UnicodeFromLocaleChars(CP_UTF8, MB_ERR_INVALID_CHARS, Pointer(Bytes),
    ByteCount, nil, 0);
  if (ByteCount>0) and (Len=0) then begin
    raise EEncodingError.CreateRes(@SNoMappingForUnicodeCharacter);
  end;
  SetLength(Result, Len);
  UnicodeFromLocaleChars(CP_UTF8, MB_ERR_INVALID_CHARS, Pointer(Bytes),
    ByteCount, Pointer(Result), Len);
end;

System.UnicodeFromLocaleChars 函数在 Windows 上包装 MultiByteToWideChar,在 POSIX 系统上包装 UnicodeFromLocaleCharsTEncoding class 利用 System.UnicodeFromLocaleChars 来执行其转换。如果您想朝相反的方向行驶,System.LocaleCharsFromUnicode.

public TEncoding.GetString() 方法只支持动态数组,但您可以使用 TEncoding.GetCharCount() and TEncoding.GetChars() 的受保护 PByte 重载,例如:

type
  TEncodingHelper = class(TEncoding)
  public
    function GetString(Bytes: PByte; ByteCount: Integer): String;
  end;

function TEncodingHelper.GetString(Bytes: PByte; ByteCount: Integer): String;
begin
  SetLength(Result, GetCharCount(Bytes, ByteCount));
  GetChars(Bytes, ByteCount, PChar(Result), Length(Result));
end;

var
  S: string;
begin 
  S := TEncodingHelper(TEncoding.UTF8).GetString(PByte(@arr[index]), ByteCount);
end;

或者:

type
  TEncodingHelper = class helper for TEncoding
  public
    function GetString(Bytes: PByte; ByteCount: Integer): String;
  end;

function TEncodingHelper.GetString(Bytes: PByte; ByteCount: Integer): String;
begin
  SetLength(Result, Self.GetCharCount(Bytes, ByteCount));
  Self.GetChars(Bytes, ByteCount, PChar(Result), Length(Result));
end;

var
  S: string;
begin 
  S := TEncoding.UTF8.GetString(PByte(@arr[index]), ByteCount);
end;