【问题标题】:Searching for Unicode chars from a raw byte array - Free Pascal\Lazarus or Delphi从原始字节数组中搜索 Unicode 字符 - 免费 Pascal\Lazarus 或 Delphi
【发布时间】:2012-04-18 21:32:52
【问题描述】:

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

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

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

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

谁能帮帮我?

【问题讨论】:

    标签: delphi unicode bytearray freepascal


    【解决方案1】:

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

    如果您可以假设文件名始终以驱动器号和路径开头,那么您可以一次循环一个字节的数组,直到您解码一个由'a' 之间的字符组成的六字节 UTF-16 序列-'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;
    

    【讨论】:

      【解决方案2】:

      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,具体取决于它是否大端或小端。)

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2022-01-08
        • 1970-01-01
        • 1970-01-01
        • 2019-05-12
        • 1970-01-01
        • 1970-01-01
        • 2013-09-22
        相关资源
        最近更新 更多