vitaly_l писал(а):Move(s[1], Data^, Size - 1); <== вот здесь непонятно почему s[1]??? А просто s почему нельзя? Зачем [1]???
(PChar(Data) + Size - 1)^ := #0; <== вот этот код, не понимаю, что делает?
Паскалевская короткая строка в s[0] хранит актуальную длину (ту, что возвращает Length[s]), данные начинаются с 1-го элемента -- s[1]. Для длинных строк, AnsiString, данные тоже начинаются в s[1].
-- PChar(Data) -- преобразование Data типа pointer к типу PChar,
-- PChar(Data) + Size - 1 -- вычисление указателя на последний символ выделенного блока,
-- (PChar(Data) + Size - 1)^ -- тот самый последний символ выделенного блока ...
-- (PChar(Data) + Size - 1)^ := #0 -- ... которому присваивается #0, чтобы сформировать ASCIIZ строку.
Кстати, вот немного расширенный пример для иллюстрации:
- Код: Выделить всё
{$H+}// это нам дано
const
EOL = #13#10;
type
PChunkRec = ^TChunkRec;
TChunkRec = record
Size: integer;
Data: pointer;
end;
TReadCallback = procedure(Chunk: TChunkRec; Data: Pointer); cdecl;
procedure LoadFromFile(var F: text; ReadCallback: TReadCallback; UserData: Pointer);
var
Chunk: TChunkRec;
s, l: string;
i, n: integer;
begin
while not SeekEof(F) do with Chunk do begin
ReadLn(F, n);
s := '';
for i := n downto 1 do begin
ReadLn(F, l); s := s + l + EOL;
end;
Size := Length(s) + 1;
GetMem(Data, Size);
Move(s[1], Data^, Size - 1);
(PChar(Data) + Size - 1)^ := #0;
if ReadCallback <> nil then ReadCallback(Chunk, UserData);
FreeMem(Data);
end;
end;
// это дописываем мы для работы LoadFromFile
procedure MyHandler(Chunk: TChunkRec; UserData: Pointer); cdecl;
begin
with Chunk do WriteLn(Size, EOL, PChar(Data));
end;
procedure HexDump(Chunk: TChunkRec; UserData: Pointer); cdecl;
const
HD: array [0..15] of char = '0123456789ABCDEF';
var
p: PChar;
begin
with Chunk do begin
WriteLn(Size);
p := Data;
if p<> nil then
while p^ <> #0 do begin
Write(HD[Byte(p^) shr 4], HD[Byte(p^) and $F], ' ');
Inc(p);
if (p-Data) and $F = 0 then WriteLn;
end;
if (p-Data) and $F <> 0 then WriteLn;
WriteLn;
end;
end;
var
f: text;
begin
Assign(f, 'tst.txt'); Reset(f);
LoadFromFile(f, @MyHandler, nil);
Close(f);
Assign(f, 'tst.txt'); Reset(f);
LoadFromFile(f, @HexDump, nil);
Close(f);
end.
- Код: Выделить всё
29
Это фрагмент 1 из 1 строки
29
Это фрагмент 2
из 2 строк
30
Это фрагмент 3
из 3
строк
29
Это фрагмент 4 из 1 строки
29
9D E2 AE 20 E4 E0 A0 A3 AC A5 AD E2 20 31 20 A8
A7 20 31 20 E1 E2 E0 AE AA A8 0D 0A
29
9D E2 AE 20 E4 E0 A0 A3 AC A5 AD E2 20 32 0D 0A
A8 A7 20 32 20 E1 E2 E0 AE AA 0D 0A
30
9D E2 AE 20 E4 E0 A0 A3 AC A5 AD E2 20 33 0D 0A
A8 A7 20 33 0D 0A E1 E2 E0 AE AA 0D 0A
29
9D E2 AE 20 E4 E0 A0 A3 AC A5 AD E2 20 34 20 A8
A7 20 31 20 E1 E2 E0 AE AA A8 0D 0A