264 lines
16 KiB
HTML
264 lines
16 KiB
HTML
|
||
<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<T>":</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<T>; </t>
|
||
<br><t style="margin-left: 10px">f := new BlockFileOf<T>;//В отличии от file of T - BlockFileOf<T> надо всегда инициализировать </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<T>; </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<byte>('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<T>":</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<integer>('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<T>" все 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<T>":</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<integer>('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<T>.ToSeq" работает так же как и "(file of T).ReadElements" (если не считать более продвинутой защиты от дурака):<br>
|
||
Они оба читают файл по 1 элементу, и после каждого из них проверяют, не достигнут ли конец файла.<br>
|
||
<br>
|
||
Но в "BlockFileOf<T>" есть альтернатива - "ToSeqBlocks".<br>
|
||
Эта функция читает всё из файла блоками заданной (в байтах) длины. Если её не задать - будет по умолчанию, то есть 4КБ.<br>
|
||
В нашем случае, "integer" занимает 4 байта в памяти, значит в каждом блоке по 4КБ поместится 1024 элемента типа "integer"<br>
|
||
(Объём типа T можно узнать из свойства "BlockFileOf<T>.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<integer>('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<r1>('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<T>" подходит к этому с другой стороны.<br>
|
||
Когда вы первый раз инициализируете переменную типа "BlockFileOf<r1>" -<br>
|
||
объём в памяти занимаемый переменными типа "r1" вычисляется и сохраняется во внутрее статичное поле<br>
|
||
(Его можно получить через свойство "TSize")<br>
|
||
И когда вызывается функция "Read" - "BlockFileOf<T>" читает из файла столько байт, сколько занимают переменные типа "r1",<br>
|
||
А потом копирует содержимое полученного массива байт в результат.<br>
|
||
<br>
|
||
То есть, "file of T" читает 3 блока, а "BlockFileOf<T>" только 1.<br>
|
||
И когда объём данных одинаковый - количество блоков очень важный фактор.<br>
|
||
Поэтому "BlockFileOf<T>" будет быстрее.<br>
|
||
И размер 1 блока не ограничивается размером 1 переменной типа "r1".<br>
|
||
"Read(10)", к примеру, прочитает 1 блоком то, что "file of T" читал бы как 30 блоков.<br>
|
||
<br>
|
||
Ну и, конечно, всё то же самое касается и "Write", не только "Read".<br>
|
||
<hr />
|
||
</div>
|
||
|
||
|
||
</body>
|
||
|
||
</html> |