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

264 lines
16 KiB
HTML
Raw Permalink Normal View History

<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>
Перед тем как начать, хоть уточнить:<br>
Ожидается что у вас есть хоть какое то представление о "file of T".<br>
Конечно, без того можно разобраться, но будет сложнее.
<hr />
<p onClick="toggle_show('decl')"><font size="4" color="008000" style="cursor: pointer">Объявление</font></p>
<div id=decl style="display: none">
<font size="3">"file of T":</font>
<p class=code_block>
<t style="margin-left: 00px">begin </t>
<br><t style="margin-left: 10px">var f: file of T; </t>
<br><t style="margin-left: 10px">Assign(f, 'temp.bin'); </t>
<br><t style="margin-left: 00px">end. </t>
</p>
<font size="3">"BlockFileOf&ltT>":</font>
<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">begin </t>
<br><t style="margin-left: 10px">var f: BlockFileOf&ltT>; </t>
<br><t style="margin-left: 10px">f := new BlockFileOf&ltT>;//В отличии от file of T - BlockFileOf&ltT> надо всегда инициализировать </t>
<br><t style="margin-left: 10px">f.Assign('temp.bin'); </t>
<br><t style="margin-left: 00px">end. </t>
</p>
<font size="3">Последнее можно сократить:</font>
<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">begin </t>
<br><t style="margin-left: 10px">var f := new BlockFileOf&ltT>; </t>
<br><t style="margin-left: 10px">f.Assign('temp.bin'); </t>
<br><t style="margin-left: 00px">end. </t>
</p>
<font size="3">И ещё больше сократить:</font>
<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">begin </t>
<br><t style="margin-left: 10px">var f := new BlockFileOf&ltbyte>('temp.bin'); </t>
<br><t style="margin-left: 00px">end. </t>
</p>
<hr />
</div>
<p onClick="toggle_show('io_basics')"><font size="4" color="008000" style="cursor: pointer">Основы записи/чтения</font></p>
<div id=io_basics style="display: none">
<font size="3">"file of T":</font>
<p class=code_block>
<t style="margin-left: 00px">begin </t>
<br><t style="margin-left: 10px">var f: file of integer; </t>
<br><t style="margin-left: 00px"> </t>
<br><t style="margin-left: 10px">Rewrite(f, 'temp.bin'); </t>
<br><t style="margin-left: 10px">f.Write( </t>
<br><t style="margin-left: 20px">1,2,3,4,5 </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: 10px">Reset(f); </t>
<br><t style="margin-left: 10px">loop 5 do </t>
<br><t style="margin-left: 20px">f.Read.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>
<font size="3">"BlockFileOf&ltT>":</font>
<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">begin </t>
<br><t style="margin-left: 10px">var f := new BlockFileOf&ltinteger>('temp.bin'); </t>
<br><t style="margin-left: 00px"> </t>
<br><t style="margin-left: 10px">f.Rewrite; </t>
<br><t style="margin-left: 10px">f.Write( </t>
<br><t style="margin-left: 20px">1,2,3,4,5 </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: 10px">f.Reset; </t>
<br><t style="margin-left: 10px">f.Read(5).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>
В случае с "BlockFileOf&ltT>" все 5 элементов читаются как 1 блок памяти.<br>
В то время как "file of T" может прочитать только по 1 элементу.<br>
<hr />
</div>
<p onClick="toggle_show('to_seq')"><font size="4" color="008000" style="cursor: pointer">Перечисление всех элементов в файле</font></p>
<div id=to_seq style="display: none">
<font size="3">"file of T":</font>
<p class=code_block>
<t style="margin-left: 00px">begin </t>
<br><t style="margin-left: 10px">var f: file of integer; </t>
<br><t style="margin-left: 00px"> </t>
<br><t style="margin-left: 10px">Rewrite(f, 'temp.bin'); </t>
<br><t style="margin-left: 10px">f.Write( </t>
<br><t style="margin-left: 20px">1,2,3,4,5 </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: 10px">Reset(f); </t>
<br><t style="margin-left: 10px">f.ReadElements.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>
<font size="3">"BlockFileOf&ltT>":</font>
<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">begin </t>
<br><t style="margin-left: 10px">var f := new BlockFileOf&ltinteger>('temp.bin'); </t>
<br><t style="margin-left: 00px"> </t>
<br><t style="margin-left: 10px">f.Rewrite; </t>
<br><t style="margin-left: 10px">f.Write( </t>
<br><t style="margin-left: 20px">1,2,3,4,5 </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: 10px">f.Reset; </t>
<br><t style="margin-left: 10px">f.ToSeq.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>
"BlockFileOf&ltT>.ToSeq" работает так же как и "(file of T).ReadElements" (если не считать более продвинутой защиты от дурака):<br>
Они оба читают файл по 1 элементу, и после каждого из них проверяют, не достигнут ли конец файла.<br>
<br>
Но в "BlockFileOf&ltT>" есть альтернатива - "ToSeqBlocks".<br>
Эта функция читает всё из файла блоками заданной (в байтах) длины. Если её не задать - будет по умолчанию, то есть 4КБ.<br>
В нашем случае, "integer" занимает 4 байта в памяти, значит в каждом блоке по 4КБ поместится 1024 элемента типа "integer"<br>
(Объём типа T можно узнать из свойства "BlockFileOf&ltT>.TSize", или с помощью sizeof(T) )<br>
В случае с 5 элементами это едва ли даст преимущество, но если записывать и считывать сразу много элементов - считывание блоками будет на много быстрее:
<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">begin </t>
<br><t style="margin-left: 10px">var f := new BlockFileOf&ltinteger>('temp.bin'); </t>
<br><t style="margin-left: 00px"> </t>
<br><t style="margin-left: 10px">f.Rewrite; </t>
<br><t style="margin-left: 10px">f.Write( </t>
<br><t style="margin-left: 20px">1,2,3,4,5 </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: 10px">f.Reset; </t>
<br><t style="margin-left: 10px">var blocks := f.ToSeqBlocks; </t>
<br><t style="margin-left: 10px">var AsSeq := blocks.SelectMany(bl->bl); </t>
<br><t style="margin-left: 10px">AsSeq.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>
"AsSeq := blocks.SelectMany(bl->bl)" здесь делает так, что хоть всё считывается из файла блоками,<br>
переменную "AsSeq" будет воспринимать как последовательность элементов, а не последовательность блоков.<br>
И - я расписал вывод как 3 строчки чтоб было виднее. Можно и сократить:
<p class=code_block>
<t style="margin-left: 10px">f.Reset; </t>
<br><t style="margin-left: 10px">f.ToSeqBlocks.SelectMany(bl->bl).Print; </t>
<br><t style="margin-left: 10px">f.Close; </t>
</p>
<hr />
</div>
<p onClick="toggle_show('bfo_record')"><font size="4" color="008000" style="cursor: pointer">Основное преимущество: сохранение записей (record)</font></p>
<div id=bfo_record 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">r1=record </t>
<br><t style="margin-left: 20px">b1:byte; </t>
<br><t style="margin-left: 20px">i:integer; </t>
<br><t style="margin-left: 20px">b2:byte; </t>
<br><t style="margin-left: 00px"> </t>
<br><t style="margin-left: 20px">constructor(b1:byte; i:integer; b2:byte); </t>
<br><t style="margin-left: 20px">begin </t>
<br><t style="margin-left: 30px">self.b1 := b1; </t>
<br><t style="margin-left: 30px">self.i := i; </t>
<br><t style="margin-left: 30px">self.b2 := b2; </t>
<br><t style="margin-left: 20px">end; </t>
<br><t style="margin-left: 20px">///Эта функция определяет, как данную запись выведет на экран </t>
<br><t style="margin-left: 20px">function ToString:string; override := </t>
<br><t style="margin-left: 20px">$'r1(b1={b1}, i={i}, b2={b2})'; </t>
<br><t style="margin-left: 10px">end; </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&ltr1>('temp.bin'); </t>
<br><t style="margin-left: 00px"> </t>
<br><t style="margin-left: 10px">f.Rewrite; </t>
<br><t style="margin-left: 10px">f.Write( </t>
<br><t style="margin-left: 20px">new r1(1,2,3) </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: 10px">f.Reset; </t>
<br><t style="margin-left: 10px">writeln(f.Read); </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>
Казалось бы, тот же самый код будет работать и для "file of T".<br>
Но вся разница находится в реализации:<br>
<br>
"file of T" в данном случае, при вызове "Read" сначала прочитал бы названия и типы полей "r1" из его типа (через "System.Runtime"),<br>
а затем, по очереди, читал бы из файла значение того же типа, что и у поля ("byte", затем "integer" и снова "byte"),<br>
сохраняя прочитаные значения в соответствующих полях результата.<br>
<br>
А "BlockFileOf&ltT>" подходит к этому с другой стороны.<br>
Когда вы первый раз инициализируете переменную типа "BlockFileOf&ltr1>" -<br>
объём в памяти занимаемый переменными типа "r1" вычисляется и сохраняется во внутрее статичное поле<br>
(Его можно получить через свойство "TSize")<br>
И когда вызывается функция "Read" - "BlockFileOf&ltT>" читает из файла столько байт, сколько занимают переменные типа "r1",<br>
А потом копирует содержимое полученного массива байт в результат.<br>
<br>
То есть, "file of T" читает 3 блока, а "BlockFileOf&ltT>" только 1.<br>
И когда объём данных одинаковый - количество блоков очень важный фактор.<br>
Поэтому "BlockFileOf&ltT>" будет быстрее.<br>
И размер 1 блока не ограничивается размером 1 переменной типа "r1".<br>
"Read(10)", к примеру, прочитает 1 блоком то, что "file of T" читал бы как 30 блоков.<br>
<br>
Ну и, конечно, всё то же самое касается и "Write", не только "Read".<br>
<hr />
</div>
</body>
</html>