2

理由と方法の説明で人々を退屈させたくないので、すぐに飛び込みます.

生のバイトデータを含むバイト配列があります。配列は 1000 バイトです。その 1000 バイトの配列を調べて、ファイル名に似ている可能性のある UTF-16 Unicode 文字のみを抽出したいのですが、その 1000 バイトの配列のどこに文字が表示されるか正確にはわかりません。

私はLazarus Unicode Pageこれを読み ましたが、私の問題に対する構文上のアプローチについてはまだ確信が持てません。Unicode char のサイズは最大 4 バイトですが、通常は 2 つ (文字とスペース) であることを理解しています。

UTF8encode(WideCharLenToString(@MyArray,SomeIntValue) を使用して、特定の Unicode 文字が私が尋ねたこのスレッドのさらに先に存在することを知っている他の領域で成功し、現在解決されています。配列内の別の理由. 例: "最初の 16 バイトを見てください。Unicode ですか? そうでない場合は、次の 16 を見てください。Unicode ですか? もしそうなら、それらを文字列に変換して表示します" .

誰でも私を助けることができますか?

4

2 に答える 2

5

バイトの実際のレイアウトやファイル名のフォーマット (ドライブ文字とパスがあるか、UNC パスを使用しているか、それとも単なるファイル名であるか) を知らずに、ファイル名の境界を探します。弦は難しそう。

ファイル名が常にドライブ文字とパスで始まると想定できる場合は、'a'-'z'または'A'-と'Z'それに続く':'andの間の文字で構成される 6 バイトの UTF-16 シーケンスをデコードするまで、配列を 1 バイトずつループできます。'\'文字。それが見つかった場合は、デコードされたヌル文字または有効な 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 の間の値を持つコードポイントは、1 つの完全な Unicode 文字を作成するために、DC00 から DFFF の範囲の値が続く必要があります。) 有効な UTF-16 を探しているだけでは、あまりうまくいかないでしょう。.ext のようなファイル名で見つかった特定のパターンを調べる必要があります (これは、UTF-16 で \00.\00e\00x\00t または .\00e\00x\00t\00 としてエンコードされます。ビッグエンディアンまたはリトルエンディアン。)

于 2012-04-20T08:42:43.440 に答える