2

我不想解释为什么和如何让人们感到厌烦,所以我会直接跳进去。

我有一个包含原始字节数据的字节数组。该数组为 1000 个字节。我想遍历那个 1000 字节的数组,只提取可能类似于文件名的 UTF-16 Unicode 字符,但我不知道字符出现在那个 1000 字节数组中的确切位置。

我已经阅读了 Lazarus Unicode Page这个,但我仍然对我的问题的句法方法有些不确定。我知道 Unicode 字符的大小最多为 4 个字节,但通常是两个(一个字母和一个空格)。

我已经成功地使用了 UTF8encode(WideCharLenToString(@MyArray,SomeIntValue) 在我知道某些 Unicode 字符存在于我询问的该线程的其他区域并且现在已解决。但我现在需要“寻找”它们,因为一个不同的原因,在数组中。例如“查看前 16 个字节。它们是 Unicode 吗?如果不是,请查看接下来的 16 个。它们是 Unicode 吗?如果是,将它们转换为字符串并显示它们”

谁能帮我?

4

2 回答 2

5

在不知道字节的实际布局或文件名格式的情况下(是否有驱动器号和路径,是否使用 UNC 路径,或者它本身只是一个文件名?),寻找文件名的边界字符串会很困难。

如果您可以假设文件名始终以驱动器号和路径开头,那么您可以一次循环一个字节的数组,直到您解码一个六字节的 UTF-16 序列,该序列由'a'-'z''A'-之间的字符组成,'Z'后跟':''\'人物。如果发现这种情况,请继续解码 UTF-16 序列,直到遇到解码的空字符或不是有效 UTF-16 序列的二进制值,例如:

var
  Buffer: array[0..1000-1] of Byte;
  I: Integer;
  PCh: PWord;
  Hi, Lo: Word;
  Ch: Cardinal;
  PStart: PWideChar;
  Len: Integer;
  FileName: WideString;
begin
  ...

  I := 0;
  while I <= (SizeOf(Buffer)-6) do
  begin
    PCh := PWord(@Buffer[I]);
    if not (((PCh^ >= Ord('a')) and (PCh^ <= Ord('z'))) or ((PCh^ >= Ord('A')) and (PCh^ <= Ord('Z')))) then
    begin
      Inc(I);
      Continue;
    end;
    Inc(PCh);    
    if PCh^ <> Ord(':') then
    begin
      Inc(I);
      Continue;
    end;
    Inc(PCh);
    if PCh^ <> Ord('\') then
    begin
      Inc(I);
      Continue;
    end;
    PStart := PWideChar(@Buffer[I]);
    Len := 0;
    Inc(I, 6);
    Inc(PCh);
    while I <= (SizeOf(Buffer)-2) do
    begin
      if (PCh^ < $D800) or (PCh^ > $DFFF) then
      begin
        Ch := Cardinal(PCh^);
        Inc(I, 2);
        if Ch = 0 then Break;
        Inc(Len);
      end else
      begin
        if PCh^ > $DBFF then Break;
        if (I+2) = SizeOf(Buffer) then Break;
        Hi := PCh^;
        Inc(PCh);
        if (PCh^ < $DC00) or (PCh^ > $DFFF) then Break;
        Lo := PCh^;
        Ch := ((Cardinal(Hi) - $D800) * $400) + (Cardinal(Lo) - $DC00) + $10000;
        if Ch > $10FFFF then Break;
        Inc(I, 4);
        Inc(Len, 2);
      end;
    end;
    SetString(FileName, PStart, Len);
    if Len > 0 then
    begin
      ... use FileName as nedeed...
    end;
  end;
  ...
end;
于 2012-04-19T00:05:03.967 回答
0

UTF-16 代码点的长度为 2 个字节或 4 个字节。这不是一个字母和一个空格;单独来看,大多数 16 位字都是有效的 UTF-16 字符。(值在 D800 和 DBFF 之间的代码点需要后跟 DC00-DFFF 范围内的值才能构成一个完整的 Unicode 字符。)如果您只是在寻找有效的 UTF-16,那么您不太可能取得很大进展。您需要查看在文件名中找到的特定模式,例如 .ext(将在 UTF-16 中编码为 \00.\00e\00x\00t 或 .\00e\00x\00t\00,具体取决于它是否大端或小端。)

于 2012-04-20T08:42:43.440 回答