2018-09-26 01:50:40 +03:00
< html >
< head >
2018-11-07 23:35:50 +03:00
< meta http-equiv = "Content-Type" content = "text/html; charset=utf-8" / >
2018-09-26 01:50:40 +03:00
< 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<T>; < / t >
< br > < t style = "margin-left: 10px" > f := new BlockFileOf<T>; //В отличии от 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<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& 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<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& 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<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& 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<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& 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 >