В случае кодирования ключевого параметра FLDT процедура дополнительно позволяет сохранять FLDT для файла данных F в файле, путь к которому определяется как cat(F, ".m"). Последующие вызовы FTabLine(F) в случае доступности такого m-файла активируют глобальную переменную с именем, указываемым в выводимом сообщении. В общем случае имя имеет следующий вид aaa_bbb_fldt, где aaa.bbb – имя F файла. Такая возможность оказывается довольно полезной, если файл не подвергается частым обновлениям.
Наряду с представленными, нами был создан ряд других полезных средств для работы с файлами данных TEXT-типа. В частности, процедуры {writedata1, readdata1} существенно расширяют возможности стандартных процедур {writedata, readdata}, обеспечивая сохранение в файле данных любого типа {list, listlist, vector, matrix, Matrix}. При этом, сохраняемые данные формируются построчно с разделением их в строках пробелами.
Процедуры DAopen, DAread и DAclose обеспечивают поддержку прямого доступа к файлам TEXT-типа (и даже более общего rlb-типа), точнее к его строкам-записям. Процедура DAopen(F) предназначена для открытия произвольного TEXT-файла данных, заданного полным путем к нему в режиме прямого доступа к его записям (строкам) согласно их номерам в файле. В результате успешного вызова данной процедуры создается специальный файл данных (доступный в том же каталоге, что и исходный файл F). Данный файл содержит таблицу, чьи входы – номера строк файла F, тогда как выходы – соответствующие им позиции в файле. В результате вызова процедуры DAopen(F) производится активизация в текущем сеансе таблицы, соответствующей файлу данных F.
После этого, посредством вызовов процедуры DAread(F, n) в текущем Maple-сеансе мы получаем доступ непосредственно к n-й записи файла данных F, возвращая ее значение. С таким файлом данных можно одновременно работать и стандартными средствами доступа, принимая во внимание влияние вызовов процедуры DAread(F, n) на позиционирование указателя текущей записи F-файла. Закрытие файла F, открытого по вызову DAopen(F), производится вызовом процедуры DAclose(F), который обеспечивает как естественное закрытие F-файла, так и удаление файла с сопутствующей ему таблицей, а также деактивацию в текущем сеансе соответствующей таблицы. Ниже приведен пример применения указанных средств с оценкой получаемого временного выигрыша.
> F:= "C:/Academy/TRG.txt": for k to 10000 do writeline(F,cat("", k)) end do: Close(F); t:= time(): for k to 10000 do readline(F) end do: time() - t; All_Close(); ⇒ 3.316 > DAopen(F); t:=time(): DAread(F, 3000), time() - t; t:=time(): DAread(F, 6000), time() - t;
"3000", 0.655
"6000", 0.622
Наряду с представленными, для файлов данных ТЕХТ-типа нами был создан ряд достаточно полезных средств различного назначения, с которыми можно ознакомиться в [41, 103,108,109]. Многие из них представляют не только чисто практический интерес, но и с учебной точки зрения полезны, используя эффективные приемы программирования алгоритмов, специфических для задач доступа к текстовым файлам данных.
Выше нами были рассмотрены средства работы с текстовыми файлами на уровне логических записей, в качестве которых выступали выражения string-типа – текстовые строки, разделяемые управляющими hex(0D0A)-символами «перевода строки и возврата каретки». Для обеспечения доступа к файлам на уровне произвольных выражений Maple-язык располагает функциями writestat и readstat, обеспечивающими соответственно запись и чтение логических записей, в качестве которых выступают последовательности Mapleвыражений, разделенные запятой и завершающиеся управляющими hex(0D0A)-символами «перевода строки и возврата каретки». В этом отношении указанные средства также имеют дело с внешними файлами TEXT-типа.
По функции writestat(<СФ>,V1,...,Vn) производится операция записи в текстовый файл, определяемый первым СФ-аргументом (спецификатор файла или номер приписанного ему логического канала), последовательности Vk-выражений, завершающейся управляющим hex(0D0A)-символом «перевода строки и возврата каретки». При этом сами элементы последовательности разделяются запятой. Если отсутствует второй фактический аргумент функции, то ее вызов производит запись в файл пустой строки, т.е. просто управляющий hex(0D0A)-символ. В случае успешного завершения вызова writestat-функции возвращается записанное за операцию количество символов. Если до вызова writestat-функции принимающий файл был закрыт, то он открывается как TEXT-файл STREAM-вида в режиме WRITE доступа, полностью обновляя существующий файл. Относительно стандартных файлов default и terminal функция ведет себя аналогично случаю writeline-функции доступа. При записи в файл Maple-выражений они проверяются на синтаксическую корректность; при этом, вызов функции writestat(default, V1, ..., Vn) эквивалентен вызову lprint(V1, ...,Vn)-функции вывода на печать. Если до применения writestat-функции файл был создан как файл {STREAM|RAW}-вида и открыт в READ-режиме доступа, то по writestat-функции он переоткрывается как TEXT-файл в WRITE-режиме доступа, не изменяя текущей позиции сканирования, т.е. допускается операция записи в файл, начиная с требуемой его позиции.
> F:= "C:/ARM_Book/Academy/REA.07": readline(F); iostatus(); close(F);
"Mathematical Theory of Homogeneous Structures (Cellular Automata)"
[1, 0, 7, [0, "C:/ARM_Book/Academy/REA.07", STREAM, FP=6913794, READ, TEXT]]
> writestat(F, [V = 64, G = 59, S = 39], Z = sqrt(V^2 + G^2 + S^2)); ⇒ 50
> writestat(F, `Package Maple 8`, `Professional Edition`, `Release 8`); ⇒ 55
> close(F): readline(F); readline(F), readline(F);
"[V = 64, G = 59, S = 39], Z = (V^2+G^2+S^2)^(1/2)"
"`Package Maple 8`, `Professional Edition`, `Release 8`", 0
В приведенном фрагменте считывается первая строка текстового F-файла и по iostatusфункции определяются характеристики открытого файла. После этого, двумя вызовами writestat-функции в закрытый файл помещаются записи, содержащие последовательности Maple-выражений, полностью обновляя содержимое существующего файла, что подтверждает последующее его считывание тремя вызовами readline-функции. В случае открытого файла TEXT-типа по writestat-функции производится дозапись в него по месту установки указателя в результате последней операции с файлом.
Следует иметь ввиду, что файлы данных, созданные writestat-функцией, не читаются предложением read. Для этих целей можно использовать несложную процедуру wsread, исходный текст которой и примеры применения иллюстрирует следующий фрагмент.
wsread := proc (F::file) local a; if member(readbytes(F TEXT, , ∞)[-1], {":" ";", }) then close(F), WARNING "datafile is ready for the read call"( ) else assign(a = cat("`_Res$$$`:=", readline(F), ";")), filepos(F, 0), writeline(F a, ), close(F); WARNING("datafile <%1> had been converted in situ", F) end if ; if 1 < nargs then read F; WARNING( "result is in the variable `_Res$$$` if datafile had been converted") end if end proc > writestat("D:\work\aladjev/datafile", (a+b)/(c+d), (x+y)^2, parse("assign(Proc=proc() `+`(args) end proc)")); ⇒ 64 > iostatus(); [1, 0, 7, [0, "D:/work/aladjev/datafile", STREAM, FP = 2009398496, WRITE, TEXT]] > wsread("D:/work/aladjev/datafile"); Warning, datafile <D:/work/aladjev/datafile> had been converted in situ > writestat("D:/work/aladjev/datafile",(a+b)/(c+d),(x+y)^2,parse("assign(Proc=proc() `+`(args) end proc)")); ⇒ 64 > wsread("D:/work/aladjev/datafile", 18); Warning, result is in the variable `_Res$$$` > `_Res$$$`; a + b, (x + y)2 c + d > Proc(64, 59, 39, 44, 10, 18); ⇒ 234 |
Первый аргумент процедуры определяет искомый файл, как правило, созданный процедурой writestat. Тогда как второй необязательный аргумент (произвольное Maple-выражение) определяет режим обработки исходного файла F. Если файл читаем предложением read, то при наличии второго аргумента он загружается в текущий сеанс. Иначе выводится соответствующее сообщение. Если же файл F был создан writestat-процедурой, то он конвертируется «на месте» в файл, пригодный для чтения read-предложением, с выводом соответствующего сообщения. Тогда как при наличии второго необязательного аргумента отконвертированный файл дополнительно загружается в текущий сеанс; результат загрузки становится доступным через `_Res$$$`-переменную.
По функции {writeto|appendto}(<СФ>) производится переключение режима вывода информации всех последующих Input- и Output-параграфов текущего сеанса в файл, указанный фактическим СФ-аргументом (спецификатором, но не номером логического канала), в режиме доступа соответственно {обновления|дописывания}. Таким образом, все последующие за вызовом функции результаты вычислений, не отображаясь на экране, непосредственно выгружаются в принимающий файл, определенный СФ-аргументом функции {writeto|appendto}. Выход из данного режима обеспечивает вызов writeto(terminal).
Если в качестве принимающего СФ-файла определен уже существующий файл, то он в зависимости от функции {writeto|appendto} соответственно полностью обновляется либо дополняется новой информацией текушего сеанса.
Из анализа содержимого СФ-файла следует, что в нем оказывается, собственно говоря, протокол текущего сеанса. Таким образом, рассмотренное средство предполагает ряд интересных приложений (протоколирование работы с пакетом, хранение результатов вычислений и т.д.). Так, например, следующий простой фрагмент иллюстрирует результат использования сохраненного протокола части текущего сеанса работы с пакетом.
> F:= "C:/temp/program.txt": writeto(F);
> P:= proc() `+`(args)/nargs end proc: M:= module() export x; x:= () -> `*`(args) end module:
> writeto(terminal);
> n:= fopen(F, READ): while not Fend(n) do writeline(cat(F, 1), readline(n)[2..-1]) end do:
> restart; F:= "C:/temp/program.txt1": read(F); P(42,47,67,89,95,62), M:- x(64,59,39,44,10,17);
67, 1101534720
Определяется режим записи текущего документа в заданный F-файл, в котором сохраняется вторая строка фрагмента, после чего производится выход из writeto-режима. На следующем шаге файл F обрабатывается путем удаления из всех его строк первых «>»символов, и результат обработки сохраняется в файле cat(F,1). Затем выполняется предложение restart, определяется путь к полученному файлу, который и загружается в текущий сеанс по предложению read, делая доступными находящиеся в нем процедуру P и модуль M. Представленный фрагмент дает некоторое представление о путях возможного использования writeto-режима. Как правило, более серьезное его использование требует и более сложного алгоритма обработки полученного в таком режиме файла, содержащего протокол части текущего сеанса. Между тем, данный режим скрывает и все сообщения пакета, что требует определенной осмотрительности. В этом отношении наиболее эффективным применение данного режима предполагается в процедурах либо файлах с Maple-программами, загружаемыми по read-предложению (см. прилож. 3 [12]).