"Offset" (он же отступ) — кол-во байт в начале файла, которые не будут использоваться под элементы, сохранённые в файл.
При этом, эту область можно использовать под что угодно другое.
Чаще всего — под заголовок файла, описывающий какую-то общую для всех элементов файла информацию.
Если у файла есть отступ — "Size" и "Pos" будут учитывать его.
То есть, если длина файла 11 байт, один элемент занимает 2 байт, а отступ 3 байт - "Size" будет возвращать 4, потому что (11-3)/2 = 4.
Но, что очень важно помнить: когда файл только открыт/создан любым способом, кроме "Append" -
позиция в файле находится в самом начале, то есть на отступе.
А значит, операции чтения и записи будут начинать работать с самого начала файла, а не с конца отступа.
Поэтому, в большинстве случаев лучше вызвать "f.Pos := 0" перед чтением/записью.
Это поставит позицию в файле на элемент #0, то есть сразу после отступа.
И так, как написано выше, основное применение - заголовок файла:
uses BlockFileOfT;
type
HeaderT = record
version: integer;
public function ToString: string; override :=
$'Header: [version={version}]';
end;
ElementT = byte;
begin
var f := new BlockFileOf<ElementT>('temp.bin',sizeof(HeaderT)); // Этот конструктор установит Offset на sizeof(HeaderT)
f.Rewrite;
begin
var hf := new BlockFileOf<HeaderT>(f); // Этот конструктор создаст новый "BlockFileOf<T>", у которого будет общий фаловый поток с "f"
var h: HeaderT;
h.version := 5;
hf.Write(h);
// Эта строчка не закроет поток, потому что файл сейчас открыт в двух переменных
// Но она отвяжет "hf" от файла открытого в "f", чтобы когда "f" закрылся - файл тоже был закрыт
hf.Close;
end;
f.Write(
1,2,3,4,5,6,7,8,9
);
f.Close; // А вот теперь поток будет закрыт и файл сохранён, потому что теперь это последняя перменная, в которой открыт файл
f.Reset;
begin
var hf := new BlockFileOf<HeaderT>(f);
var h := hf.Read;
writeln(h);
hf.Close;//Опять же, надо закрыть сразу, как закончили пользоваться
end;
f.Read(9).Print;
f.Close;
end.
Прошу обратить внимание на то, что я не поставил тут "f.Pos := 0" перед чтением/записью только по стечению двух обстоятельств:
1. Этот код линейный, в нём хорошо видно, что прямо перед чтением/записью элементов идёт чтение/запись заголовка. А значит, файловый курсор сам передвинется на sizeof(HeaderT).
2. Написав этот короткий участок кода я протестировал его, чтобы быть уверенным в том, что я ничего не забыл и не перепутал.