pascalabcnet/InstallerSamples/BlockFileOfT/СправкаData/WhyOffset.html

110 lines
6.9 KiB
HTML
Raw Permalink Normal View History

2019-09-22 03:43:43 +03:00
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<style type="text/css">
.code_block {
background: #c0c0c0;
padding: 5px;
padding-right: 20px;
border: solid 1px black;
}
</style>
<script type="text/javascript">
function toggle_show(id) {
document.getElementById(id).style.display = document.getElementById(id).style.display == 'none' ? 'block' : 'none';
}
</script>
</head>
<body>
<font size="3"><a href="../Справка.html"><=</a></font><br>
<br>
<hr />
<p onClick="toggle_show('io_basics')"><font size="4" color="008000" style="cursor: pointer">Что такое "Offset"</font></p>
<div id=io_basics style="display: none">
"Offset" (он же отступ) — кол-во байт в начале файла, которые не будут использоваться под элементы, сохранённые в файл.<br>
При этом, эту область можно использовать под что угодно другое.<br>
Чаще всего — под заголовок файла, описывающий какую-то общую для всех элементов файла информацию.<br>
<br>
Если у файла есть отступ — "Size" и "Pos" будут учитывать его.<br>
То есть, если длина файла 11 байт, один элемент занимает 2 байт, а отступ 3 байт - "Size" будет возвращать 4, потому что (11-3)/2 = 4.<br>
<br>
Но, что очень важно помнить: когда файл только открыт/создан любым способом, кроме "Append" -<br>
позиция в файле находится в самом начале, то есть на отступе.<br>
А значит, операции чтения и записи будут начинать работать с самого начала файла, а не с конца отступа.<br>
Поэтому, в большинстве случаев лучше вызвать "f.Pos := 0" перед чтением/записью.<br>
Это поставит позицию в файле на элемент #0, то есть сразу после отступа.
<hr />
</div>
<p onClick="toggle_show('decl')"><font size="4" color="008000" style="cursor: pointer">Заголовки</font></p>
<div id=decl style="display: none">
И так, как написано выше, основное применение - заголовок файла:
<p class=code_block>
<t style="margin-left: 00px">uses BlockFileOfT; </t>
<br><t style="margin-left: 00px"> </t>
<br><t style="margin-left: 00px">type </t>
<br><t style="margin-left: 10px">HeaderT = record </t>
<br><t style="margin-left: 20px">version: integer; </t>
<br><t style="margin-left: 00px"> </t>
<br><t style="margin-left: 20px">public function ToString: string; override := </t>
<br><t style="margin-left: 20px">$'Header: [version={version}]'; </t>
<br><t style="margin-left: 00px"> </t>
<br><t style="margin-left: 10px">end; </t>
<br><t style="margin-left: 10px">ElementT = byte; </t>
<br><t style="margin-left: 00px"> </t>
<br><t style="margin-left: 00px">begin </t>
<br><t style="margin-left: 10px">var f := new BlockFileOf&ltElementT>('temp.bin',sizeof(HeaderT)); // Этот конструктор установит Offset на sizeof(HeaderT) </t>
<br><t style="margin-left: 10px">f.Rewrite; </t>
<br><t style="margin-left: 10px">begin </t>
<br><t style="margin-left: 20px">var hf := new BlockFileOf&ltHeaderT>(f); // Этот конструктор создаст новый "BlockFileOf&ltT>", у которого будет общий фаловый поток с "f" </t>
<br><t style="margin-left: 00px"> </t>
<br><t style="margin-left: 20px">var h: HeaderT; </t>
<br><t style="margin-left: 20px">h.version := 5; </t>
<br><t style="margin-left: 20px">hf.Write(h); </t>
<br><t style="margin-left: 00px"> </t>
<br><t style="margin-left: 20px">// Эта строчка не закроет поток, потому что файл сейчас открыт в двух переменных </t>
<br><t style="margin-left: 20px">// Но она отвяжет "hf" от файла открытого в "f", чтобы когда "f" закрылся - файл тоже был закрыт </t>
<br><t style="margin-left: 20px">hf.Close; </t>
<br><t style="margin-left: 10px">end; </t>
<br><t style="margin-left: 00px"> </t>
<br><t style="margin-left: 10px">f.Write( </t>
<br><t style="margin-left: 20px">1,2,3,4,5,6,7,8,9 </t>
<br><t style="margin-left: 10px">); </t>
<br><t style="margin-left: 10px">f.Close; // А вот теперь поток будет закрыт и файл сохранён, потому что теперь это последняя перменная, в которой открыт файл </t>
<br><t style="margin-left: 00px"> </t>
<br><t style="margin-left: 00px"> </t>
<br><t style="margin-left: 00px"> </t>
<br><t style="margin-left: 10px">f.Reset; </t>
<br><t style="margin-left: 10px">begin </t>
<br><t style="margin-left: 20px">var hf := new BlockFileOf&ltHeaderT>(f); </t>
<br><t style="margin-left: 00px"> </t>
<br><t style="margin-left: 20px">var h := hf.Read; </t>
<br><t style="margin-left: 20px">writeln(h); </t>
<br><t style="margin-left: 00px"> </t>
<br><t style="margin-left: 20px">hf.Close;//Опять же, надо закрыть сразу, как закончили пользоваться </t>
<br><t style="margin-left: 10px">end; </t>
<br><t style="margin-left: 10px">f.Read(9).Print; </t>
<br><t style="margin-left: 10px">f.Close; </t>
<br><t style="margin-left: 00px"> </t>
<br><t style="margin-left: 00px">end. </t>
</p>
Прошу обратить внимание на то, что я не поставил тут "f.Pos := 0" перед чтением/записью только по стечению двух обстоятельств:<br>
1. Этот код линейный, в нём хорошо видно, что прямо перед чтением/записью элементов идёт чтение/запись заголовка. А значит, файловый курсор сам передвинется на sizeof(HeaderT).<br>
2. Написав этот короткий участок кода я протестировал его, чтобы быть уверенным в том, что я ничего не забыл и не перепутал.
<hr />
</div>
</body>
</html>