バイトの実際のレイアウトやファイル名のフォーマット (ドライブ文字とパスがあるか、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;