从原始字节数组中搜索Unicode字符 - 免费Pascal\Lazarus或Delphi

Giz*_*eat 2 delphi unicode bytearray freepascal

我不想让人们解释为什么以及怎么这样我才会跳进去.

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

我已经阅读了 Lazarus Unicode Page这个,但我仍然不确定我的问题的语法方法.我知道Unicode字符大小最多可达4个字节,但通常是两个(字母和空格).

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

谁能帮我?

Rem*_*eau 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;
Run Code Online (Sandbox Code Playgroud)