8. ОПЕРАЦИИ С ФАЙЛАМИ
Описанная выше команда #d определяет элементы массивов по значениям. Но часто бывает полезно записать значения в файл и потом считать эти значения в другой программе или в той же самой, но в другой день. Такие операции выполняет команда
#io [op=; fir=; n=; file=; form=; mo=; le=;]
Она использует 4 текстовых параметра и один числовой параметр. Параметр [op] задает тип операции, который кодируется двумя буквами. Первая буква может быть: [r] (read - прочитать из файла) или [w] (write -записать в файл). Вторая буква может быть: [f] (format - запись числовых значений текстом по формату) или [b] (byte - запись данных типа byte) или [d] (data - запись данных типа float, int или double) или [t] (text - запись текстовых данных). Итак возможны операции
rf wf rb wb rd wd rt wt
Далее, параметр [fir] (first) равен записи первого элемента массива, как это было в командах #d и #pas, то есть указывается и тип и первый индекс, например, r(35). Параметр [n] (number) указывает сколько элементов надо записать или считать. Параметр [file] указывает путь к файлу относительно "рабочей папки". Если рабочая папка задана правильно, то достаточно имени файла. Здесь есть ограничение - значение параметра [file] не может быть длиннее 42 символов. Так что не увлекайтесь длинными именами. Если имя файла будет длиннее, его придется переименовать. Здесь полезно обсудить два различных способа задания текстовых параметров. Их можно задавать прямым текстом, например,
file=mydata.dat;
и при этом текст должен заканчиваться символом [;] как все операторы присваивания. Но можно задавать и форматированным текстом. Но при этом первым символом должен быть символ текстового формата [\] а заканчиваться такая строка должна символами \E без точки с запятой. Хотя все текстовые параметры можно так задавать, этот режим в основном используется только для задания файла и главным образом путем указания текстовой ссылки. Это очень удобно в циклах. Допустим вам в цикле необходимо прочитать 50 файлов с именами: img01.png, img02.png, . . . , img50.png.
Тогда код может быть таким.
# m=0; ... #pri img\E # a=s(4); b=s(5);
#rep 50 # m=m+1; ...
#io [op=rb; fir=i(1); n=256; file=\Ta b\I-2 m;.png\E]
#end
Естественно, что файл, задаваемый текстом не должен начинаться с символа [\]. Но это ограничение очень слабое. Этот прием называется динамической генерацией имени файла. Более сложные имена файлов можно сначала все напечатать, а затем указывать текстовыми ссылками, генерируя индекс ссылки (имя строки) по параметру цикла.
Параметр [form] (format - формат записи чисел текстом) используется только в одной операции [wf], то есть запись по формату. В операции [rf], то есть чтение по формату, автоматически читаются все возможные форматы и специально нет смысла указывать формат.
Но формат все же используется для передачи другой информации. Он должен иметь структуру
form=*N;
где вместо N должно быть число или переменная с целым значением, которое указывает сколько строк в файле будет пропущено прежде чем начнется чтение чисел.
Запись чисел по формату возможна только из массивов i() и r(). Если необходимо записать числа из других массивов, то их сначала надо переслать в эти командой #pas. Параметр [form] тоже ограничен по длине 42 символами, но все возможные форматы имеют меньшую длину, так что это ограничение формальное. Наиболее простым форматом является такой
form=*N;
где вместо N должно быть число, указывающее сколько чисел надо напечатать на одной строке. Этот формат эквивалентен текстовому формату \G (см. выше о текстовых форматах). Признаком конца строки будет ASCII код 10, то есть как в операционной системе UNIX и как в Java. Этот формат полезен для КПК. Есть еще второй формат, который имеет структуру
form=EN.M.L;
где вместо N должно быть число, указывающее сколько чисел надо напечатать на одной строке, вместо M должно быть число, указывающее сколько позиций (символов) должно быть отведено на одно число, вместо L должно быть число, указывающее сколько позиций отводится для дробной части числа. Точки между числами служат разделителями. По этому формату строка заканчивается двумя ASCII кодами 13,10, а числа записываются в экспоненциальной форме с E и десятичным разделителем служит точка. Необходимо, чтобы M было больше, чем L+7. Этот формат эквивалентен текстовому формату \B. Например, 6 чисел, записанных по формату [form=E3.10.3;] сгенерируют текст
1.000E+00 2.000E+00 3.000E+00
4.000E+00 5.000E+00 6.000E+00
Больше форматов нет. Но реально, можно организовать сколько угодно сложный формат, если сначала записать текст в текстовый массив t(), а затем скопировать его в файл.
Итак, перейдем к операциям [rt] и [wt]. Эти операции могут работать только с текстовым массивом t(), поэтому параметр [fir] должен указывать только на t(), иначе будет ошибка. Операция [rt] просто заполняет некоторую часть массива t() из файла, начиная с элемента, указанного [fir] и ровно [n] элементов. При этом сначала считывается весь файл, как текст строка за строкой, затем содержимое конвертируется в массив уникодов и берется нужное число символов. Этот режим проверялся только на первых 127 уникодах и как он работает на остальных можно проверить экспериментальным путем. После выполнения операции параметр s(4) содержит индекс первого записанного элемента в t(), а параметр s(5) - число элементов. Это общий принцип записи в текстовый массив, точно также поступает команда #pri . В любой момент параметр s(6) показывает размер записанной части массива t(). Начиная с версии 2.8.5 по этой операции можно считывать тексты из файлов, записанных внутри jar-файла программы в папку [resources]. Это удобно в режиме использования программы в виде спец-окна или проигрывателя (см. главу 25). Для этого перед именем файла надо поставить символ &. Операция [wt] наоборот, сначала конвертирует нужный кусок массива уникодов в текст и затем записывает в файл строка за строкой. При этом файл записывается целиком, а если он существовал раньше, то полностью переписывается. В этом случае признак конца строки соответсвует той операционной системе, которая используется. Например, в Windows это [13,10], хотя изначально в текстовом массиве было просто [10]. Теперь ясно, что образ будущего файла можно сформировать с помощью команды #pri и затем перенести в файл из t() целиком. При этом можно использовать всю мощь форматов команды #print.
Операции [rd] и [wd] позволяют считывать и записывать числа в компьютерном коде. Это самая сжатая форма записи и она особенно полезна для записи очень больших массивов. В этом случае дополнительно используется параметр [mo] (mode) для указания формата записи чисел. Если [mo=1;], то числа записываются и считываются в формате "float", то есть вещественные числа длиной 4 байта. Если [mo=2;], то используется формат "int" целых чисел длиной 4 байта. Если [mo=3;], то используется формат "double" для вещественных чисел длиной 8 байт. Наконец, если [mo=4;], то используется формат "short", то есть двухбайтовые знаковые целые числа. Порядок байтов как в Java, то есть старшие слева. Для данных системы Windows необходимо сначала перевернуть порядок байтов какой либо специальной процедурой. Сама ACL-программа как записывает, так и считывает и проблем не возникает. В операции [rd] возможно задавать также [mo=5;] что означает чтение двухбайтовых целых чисел без знака. При этом порядок байтов регулирует параметр [ord], если он равен нулю, то первый байт является старшим, второй младшим, как в Java, а если он отличен от нуля, например, равен 1, то младший байт первый, старший второй, как в Windows. Такой формат записи чисел используется детекторами излучения и записывается в графические файлы с расширением tif или edf. Данные считываются из файла не с самого начала, а после пропуска определенного числа байтов, задаваемого параметром [le], и не весь файл, а столько чисел, сколько указано параметром [n]. А вот записываются числа в новый файл с самого начала. Если файл существует, то он переписывается заново. Узнать размер файла при чтении можно с помощью команды #file (см. далее). Если программа считывает больше данных, чем было записано, то возникающая ошибка не блокируется и Java-интерпретатор выдаст сообщение на Терминал, если программа запущена из bat-файла. Так что надо быть внимательным. Это недоработка, каюсь. Следует понимать, что параметр [le] позволяет пропускать любое число данных перед чтением. Но указывается именно число байтов, а не чисел. Так что число пропускаемых чисел должно быть умножено на длину числа (4 или 8). При этом, если [le] отлично от нуля, то параметр s(1) возвращает реальное число байтов, сколько было на самом деле пропущено. Это число, практически всегда совпадает с тем, которое было заказано параметром [le], но в случае проблем можно проверить операцию, распечатав параметр s(1). Начиная с версии 2.8.22 по этой операции можно считывать тексты из файлов, записанных внутри jar-файла программы в папку [resources]. Это удобно в режиме использования программы в виде спец-окна или проигрывателя (см. главу 25). Для этого перед именем файла надо поставить символ &.
Операция [rb] позволяет считывать байты файла как целые числа в диапазоне от -128 до 127. В этом случае используется параметр [le] (length), который определяет число байтов в файле, перед чтением. То есть реально считывание происходит не с первого байта, а с байта, номер которого [le]+1. Если чтение происходит в текстовый массив, то к отрицательным значениям добавляется 1104, что переводит русские ASCII коды в формате Windows в русские уникоды. Это позволяет читать русские книги в текстовом формате Windows, что использовано в программе чтения книг на КПК. При записи операцией [wb]значения элементов массивов конвертируются в байты. При этом русские уникоды массива t() переводятся в отрицательные значения вычитанием 1104. Файл записывается сначала и заново создается. Эти операции позволяют манипулировать содержимым файла произвольным образом. Но следует помнить, что байтов в файле много, а ACL - язык не быстрый. Поэтому манипулировать разумно только с относительно короткими файлами.
* * * * *
Работа с файлами не ограничивается только записью и чтением данных. Есть очень много других нужных и полезных операций. По этой причине в ACL сделана специальная команда, которая так и называется #file, а короче #f. Эта команда имеет очень много операций, причем операции объединены в одну команду лишь по той причине, что они все работают с файлами. Реально некоторые операции -- это целые программы со своими параметрами и аргументами и между операциями нет никакой связи. Минимальное число символов в названии операции 4, иначе трудно разделить все названия без потери смысла.
Мы начнем описание операций по принципу от простого к сложному. Полный список операций выглядит следующим образом
fold size dele copy divi fcat find repl line list
edit html choo tobm tocm tops topng w2jc alph
Первые операции -- это те, которые обычно выполняет операционная система. Там, где специально не указано, имена файлов отсчитываются от "рабочей" папки внутри папки интерпретатора. Однако в версии 2.9.16 было снято одно ограничение. Дело в том, что команда в принципе способна работать со всеми файлами на компьютере по их абсолютным адресам, и это иногда бывает полезно. В таком режиме работы надо указать рабочую папку как null, и в параметр file записать полный адрес, начиная с буквы диска. Но полный адрес может иметь очень большой размер, а размер параметра file ограничен 42 символами. Чтобы снять это ограничение введен специальный режим [file=arg;]. В этом случае адрес файла надо задавать первым аргументом команды, и отсутствие аргумента фиксируется как ошибка. С учетом этого замечания начинаем.
#f [op=fold; file=any; emp=;]
Эта операция как раз переустанавливает "рабочую" папку, имя которой задается параметром [file] относительно папки интерпретатора. В имени можно использовать символ [/] для вложенных папок. После выполнения этой команды адрес "рабочей" папки меняется на всю работу интерпретатора, то есть и после завершения выполнения текущей ACL программы. Единственный способ переопределить "рабочую" папку -- это снова выполнить данную команду с новым значением параметра [file]. В значении параметра [file] есть два особых случая. Если [file=null;], то будет установлена папка интерпретатора вместо папки с именем [null]. Также если [file=oldf;] то будет восстановлена папка, которая была "рабочей" до последнего изменения. То есть папку с именем [oldf] тоже нельзя задать никаким способом. Просто не используйте папки с такими именами.
До версий 2007 года, если указанная рабочая папка не существовала, то она автоматически создавалась. В новых версиях используется дополнительный параметр [emp]. Если он равен нулю, то, как обычно, работает старый режим. Но если он не равен нулю и папки с указанным именем не существует, то она и не создается, а значение параметра обнуляется. То есть задавая [emp=1;] и проверяя значение параметра после операции как элемент массива s(41) можно определить - существует ли папка или нет. Если она не существует, то можно принять необходимые действия по предотвращению дальнейших операций. Это полезно в том случае, когда программа должна считывать файлы из папки, но папка не скопирована по тем или иным причинам, а создавать новую папку нежелательно.
#f [op=size; file=any;]
Эта операция определяет размер файла, имя которого задается параметром [file]. Размер возвращается в s(1). Если s(1)=0, то файла не существует.
#f [op=dele; file=any;]
Эта операция уничтожает файл на диске, имя которого указано параметром [file].
#f [op=copy; n=; file=newtotal;] file1.ext\E file2.ext\E ...
Эта команда создает новый файл с именем, которое определяет параметр [file], и с содержанием, которое является сложенными вместе содержаниями серии файлов, имена которых указывает серия аргументов в виде FT (форматированного текста). Описание FT дано выше разделе 4. Другими словами, эта операция копирует несколько файлов в один. Число копируемых файлов указывает параметр [n]. При этом число аргументов может быть больше, но не может быть меньше, иначе фиксируется ошибка. Если в качестве аргументов указываются несуществующие файлы, то ошибка не фиксируется, просто указанные файлы игнорируются. Если все файлы не существуют, то создается нулевой файл.
#f [op=divi; file=; form=; b=; le=; n=; xsh=;]
Эта операция, наоборот, позволяет разделить файл на части и записать одну часть в новый файл. Имя исходного файла определяется параметром [file], имя нового файла определяется параметром [form] (formed). Исходный файл трактуется как матрица байтов, из которого вынимается подматрица. Для выполнения этой работы необходимо 4 параметра. Параметр [b] (begin) определяет число байтов, которые пропускаются с самого начала. После этого часть байтов длиной [le] (length) записываются и затем снова пропускаются байты длиной [xsh] (xshift). Такие le-xsh операции повторяются [n] (number) раз. Новый файл будет иметь ровно [le]*[n] байтов. Эта операция полезна, например, для выделения малой части большой картинки в новую картинку. Она также может быть полезна при работе с числовыми матрицами.
#f [op=fcat; file=any;]
Эта операция возвращает каталог файлов в папке, указанной параметром [file]. Имя папки должно быть указано полностью, начиная от папки интерпретатора. Каталог записывается в текстовый массив t() начиная с индекса, определяемого параметром s(3). После записи, как обычно, s(4) и s(5) указывают начало и длину проведенной записи. Если параметр [file] указывает не на папку, то возвращается s(5)=0. Список задается одной строкой, в которой имена файлов разделяются символом вертикальной черты [|].
#f [op=find; b=; le=; file=any;]
Эта операция выполняет поиск некоторой совокупности байтов внутри файла, имя которого указывает параметр [file]. Последовательность байтов должна быть предварительно определена их значениями в целом массиве i(), причем индекс первого элемента определяет параметр [b] (begin), а число байтов определяет параметр [le] (length). Результат поиска возвращается в параметр s(2) как число повторений данной системы байтов. Важно помнить, что байты имеют значения от -128 до 127 в отличие от ASCII кодов. Например, код
#d 2 i(11) 13 10
#f [op=find; b=11; le=2; file=any;]
покажет число строк внутри файла в системах ДОС и Windows как значение s(2). Если s(2)=0, то этот файл либо имеет одну строку, либо он записан в системе UNIX-оидов, либо он числовой.
#f [op=repl; b=; le=; mo=; file=any;]
Эта операция делает более сложную работу по сравнению с предыдущей операцией. Она находит все копии одной системы байтов и заменяет их на другую систему байтов. Опять все байты, число которых равно значению параметра [le], должны быть заданы в массиве i(), начиная с индекса, определяемого параметром [b]. Но среди них [mo] первых байтов определяют систему, которая заменяется (модифицируется), а оставшиеся [le]-[mo] байтов определяют систему, которая будет записана вместо них. Новое содержание будет спасено в файле с тем же именем. Поэтому, если необходимо сохранить исходный файл, он должен быть предварительно скопирован с другим именем. Например, код
#d 2 i(11) 44 46
#f [op=repl; beg=11; len=2; mod=1; file=some.dat;]
заменит все запятые в файле на точки.
#f[op=line; file=any; n=; b=; le=; emp=;]
Эта операция читает и записывает в файл строки текста. Если параметр [n=-N;] отрицательный, то прочитывается N-я строка текста в файле и ее содержание записывается в текстовый массив t() начиная с индекса, задаваемого s(3). После операции s(4) и s(5), как обычно, показывают начало и размер записанного текста. Если N-й строки в файле нет, то параметр s(5) будет равен нулю. Наоборот, если параметр [n=N;] положительный, то в файле записывается N-я строка, содержанием которой будет часть текстового массива t(), начиная с первого элемента, индекс которого определяется параметром [b] (begin), а число символов равно значению параметра [le] (length). Если файл имел больше, чем N строк, то старое содержание N-ой строки будет изменено. Если в файле было меньше, чем N строк, он будет иметь ровно N строк. Строки между последней из бывших и N-й будут пустыми. Такой режим работы соотвествует старым версиям, когда параметр [emp=0;]. Но если параметр [emp] не равен нулю, например, [emp=1;], то при положительном [n=N;] в файле просто уничтожается N-ая строка. Параметр [emp] (enhanced mode parameter) позволяет реализовать дополнительные режимы работы команд, но он отсутствует в старых версиях, которые соответствуют нулевому значению. Поэтому не забывайте возвращать параметр [emp] в исходное состояние [emp=0;].
#f [op=list; file=any; c=; b=;]
Эта операция выполняет специальную работу. Она прочитывает файл, имя которого указано параметром [file] и создает специальную строку текста в текcтовом массиве t(). Она берет в этот текст из файла все символы начиная от начала и до символа, ASCII код которого определяется параметром [c] (code), включая и его самого. Затем она пропускает все символы после ASCII кода [c] до тех пор, пока не встретит символ с ASCII кодом [b] (begin), включая и его самого (то есть его тоже пропускает). Затем она снова берет все символы до первого появления ASCII кода [c] и так далее. Это выглядит так, как будто команда берет одну часть из двух частей записей в файл. Если запись имеет имя и тело, то команда может составить список имен. В результате число имен возвращается в параметр s(2), а сформированная строка записывается в текстовый массив t() начиная с индекса, определяемого, как обычно, параметром s(3). После операции номер первого записанного символа и число символов можно получить из параметров s(4) и s(5), аналогично другим похожим операциям. Такую работу, в принципе, можно сделать и с помощью других команд ACL, но эта операция работает намного быстрее, особенно для больших файлов. Как использовать эту операцию в реальной программе каждый программист решает сам.
Описываемые ниже операции реализуют намного более сложную работу, но эта работа делается полностью автоматически, так что использовать операции легко. А все особенности последующей работы программы можно изучить экспериментально, то есть уже в процессе работы с готовой программой.
#f [op=edit; c=; mo=; file=; b=; le=;
em=; nx=; ny=; xs=; ys=;] FT
Эта операция запускает готовый текстовый редактор для редактирования содержимого файла в отдельном окне. Имя файла, как обычно, определяется параметром [file]. Если файл отсутствует, то он будет создан. В этом случае редактор начинает с пустого текста. Отредактированное содержание будет записано в тот же файл, если [mo=1;] или не будет записано совсем, если [mo=0;]. Второй режим удобен для информационных файлов, содержание которых должно быть только показано и исправления нежелательны. При [mo=1;] файл перезаписывается автоматически при выходе из редактора по кнопке меню [Edit/Exit]. Если редактор настроен на запись измененного текста, а запись нежелательна, то можно закрыть редактор с помощью крестика в правом верхнем углу окна. Меню редактора имеет кнопки в нескольких разделах: [Edit] (Find, Find Next, Info, Change font, Wrap lines, Exit) [Convert] [Show] [Help]. Кнопки Find и Find Next стандартные. Кнопка Info сообщает информацию о размере записанного текста, координатах курсора и абсолютном положении курсора, кнопка Change font позволяет выбрать один из 5 логических фонтов и размер фонта. Эти значения хранятся в параметрах [fk] == s(27) (font kind) и [fs] == s(28) (font size). Как обычно, измененные значения параметров будут действовать до следующего определения, причем их можно изменить не только в окне редактора, а и в любом месте программы. Текущие значения этих параметров запоминаются в файле "start.acl". Логические фонты реально отсутствуют. Интерпретатор проверяет наличие фонтов на компьютере и находит реальные фонты, близкие по свойствам заявленным логическим фонтам. Так что фонты можно просто проверить эмпирически и выбрать подходящий. Режим Wrap lines регулирует показ длинных строк, они либо загибаются на краю окна, либо нет. Повторный клик отменяет предыдущий режим на второй из двух возможных. Кнопка Exit имеет очевидное значение.
Меню [Convert] позволяет преобразовывать выделенный текст из русского в английский и наоборот, если он набран при неправильной раскладке клавиатуры, а также вообще устанавливать виртуальную раскладку клавиатуры независимо от операционной системы. Есть также преобразования от прописных букв к строчным и наоборот. Иногда это бывает очень полезно. Меню Show позволяет показывать прямо из редактора вэб-сайты на компьютере и в интернете, а также картинки на компьютере. Встроенное описание работы редактора помогает разобраться с его функциями в процессе работы.
Параметр [c] учитывается аналогично другим GUI операциям. А именно, если [c=0;], то программа продолжает выполнение других команд после открытия окна редактора. Раньше это использовалось для автоматической презентации с помощью команды #robot. Сейчас команда #robot заблокирована, но режим сохранен, однако использовать его нужно с осторожностью. Если [c=1;], то программа ждет, когда пользователь закроет окно и не разрешает переходить к другим окнам. Позиция курсора при входе в редактор определяется параметром s(1) без имени. После выхода из редактора этот же параметр содержит позицию курсора перед выходом. Позиция задается номером символа в тексте начиная от начала. Первый символ имеет индекс 0. Знание позиции курсора может быть использовано, например, при чтении книг, так как позволяет запомнить место остановки чтения, и в следующий раз начать прямо с этого места. Можно найти и другие применения.
Заголовком окна является полное имя файла с учетом текущей папки. Раньше размеры окна редактора задавались стандартные, то есть 700*650, а само окно устанавливалось в центре экрана. Начиная с версии 7.7.8 можно использовать параметр [em]=s(41) для установки дополнительных режимов. Как и в команде #input (см. главу 10) параметр [em] это двухразрядное целое число. Младший (правый) разряд имеет значения 0,1,2. При этом 0 - означает старый режим, то есть окно редактора помещается в центре экрана, 1 - новый режим, при котором окно редактора (левый верхний угол) сдвинуто из левого верхнего угла экрана на число пикселей, определяемых параметрами [xs] и [ys], 2 - специальный режим для проигрывателя, при котором сдвиг отсчитывается от левого верхнего угла главного окна программы (в основной программе главное окно устанавливается на весь экран и этот режим совпадает с предыдущим). Старший разряд параметра [em] имеет два значения 0,1. При этом 0 - опять означает старый режим, при котором окно редактора имеет стандартные размеры (см. выше), 1 - новый режим, при котором размеры окна равны (700+[nx])*(Y+[ny]), где значение Y определяется автоматически как вертикальный размер экрана - 100, а параметры [nx] и [ny] задают изменение таких стандартных размеров окна. Они могут быть как положительные, так и отрицательные. Это удобно при показе таблиц с заданной шириной и высотой.
Существует специальный режим работы команды, который задается через определение [file=here;]. В этом случае редактор работает с частью текстового массива t() вместо файла. Эта часть начинается с индекса, определяемого параметром [b] и имеет [le] символов. При этом параметр [mo] должен иметь значения -1 или -2. При [mo=-1;] результат редактирования не записывается (только чтение), а при [mo=-2;] отредактированный редактором текст записывается снова в текстовый массив, начиная с индекса, определяемого параметром s(3). Как обычно, после записи параметры s(4) и s(5) показывают начало и длину записанного текста. В этом случае заголовок окна задается аргументом в виде форматированного текста, причем аргумент обязателен и его отсутствие фиксируется как ошибка.
В версии 2.9.2 при выходе из редактора сообщается каким образом был сделан выход: по кнопке меню или кликом кнопки крестика на правом конце титульной строки. В первом случае переменная &=1, во втором &=2. Иногда эта информация может быть полезной для правильной организации работы ACL программы.
#f[op=html; file=any;] FT
Эта операция дает возможность программисту показывать html-файлы, то есть запускать простой браузер. Имя файла определяет параметр [file], но в данном случае имя должно быть указано полным относительно папки интерпретатора, рабочая папка не используется. Более того, можно указывать и абсолютный путь к файлу, включая имя диска, то есть, например, [file=c:/first/second/file.html;]. Гиперссылки внутри файла показываются в отдельном окне, которое полностью накладывается на предыдущее, поэтому для того, чтобы вернуться назад, нужно просто закрыть текущее окно, или переместить новое окно в другое место. Окна показываются в режиме диалога, то есть нет возможности продвинуться дальше по программе, пока не закроете окно. Размеры окна в этой и в предыдущей операциях заданы стандартным образом, но пользователь может их изменить по своему вкусу с помощью мышки (передвигая границы). Браузер выполнен в самом простом варианте и не содержит ни меню, ни иконок. Он предназначен, в основном, для показа специально приготовленных информационных текстов, вся навигация в которых может быть организована с помощью гиперссылок. Так как размер текстовой строки параметра [file] ограничен 42 символами, то длинный путь к файлу записать не получится. Чтобы решить эту проблему введен специальный режим, а именно, можно записать [file=*N;], где N = 1, 2 или 3. В этом случае реальный путь к файлу считывается из аргумента FT, который обязан присутсвовать. При этом режим [file=*1;] используется для указания пути к файлу на локальном компьютере, а режим [file=*2;] используется для запуска страниц по адресу в интернете, но адрес надо указывать без заголовка "http://", так как заголовок подставляется автоматически. Естественно, во втором случае компьютер должен быть в сети. Однако сетевые файлы могут быть написаны так сложно, что браузер не сможет их обработать, поэтому я этой возможностью практически не пользуюсь. Хотя если записать html файлы самому и правильным образом, то все будет показано корректно. Режим [file=*3;] задает имя файла внутри jar-файла программы в папке [resources]. Это удобно при использовании программы в режиме спец-окна или проигрывателя, см. главу 25.
#f [op=choo; mo=; file=;] FT
Эта операция запускает специальную программу, называемую на языке Java именем FileChooser. FileChooser дает возможность пользователю просмотреть полную файловую структуру используемого компьютера аналогично Менеджеру файлов в Solaris OS или программе "My Computer" в Windows OS. Просмотр начинается с папки, указанной параметром [file]. Параметр [file] может указывать или на любой файл, отсчитываемый от главной папки интерпретатора или сразу на папку. Для указания главной папки, то есть папки интерпретатора, можно использовать [file=start.acl;]. Программа имеет три варианта. Если [mo=0;], то используется общая форма и показываются все файлы. Кнопка [Select] позволяет выбрать файл. Полное имя выбранного файла, отсчитываемое от папки интерпретатора будет записано в текстовый массив t(), начиная с элемента, номер которого задает параметр s(3). После операции переменная [&] равна 2 если окно закрыто крестиком или выбрана кнопка [Cancel] или 1 если выбрана кнопка [OK]. В последнем случае, как обычно, s(4) и s(5) показывают начало и длину записи имени выбранного файла. Пользователь имеет возможность выбрать файл, находящийся за пределами папки интерпретатора. В этом случае операция вернет полное имя файла. Эта возможность появилась после версии 2.8.5. В любом случае программист должен проявлять осторожность и проверять наличие выбранного файла с помощью операции [op=size;] в добавление к проверке значения переменной [&] и параметра s(5) прежде чем выполнять какую-либо операцию с выбранным файлом. Если [mo=1;], то используется специальная форма, в которой показываются только графические файлы с расширениями gif, jpg, png и с предварительным просмотром. После выбора файла его имя будет передано так же как и описано выше. Выбранное имя программист может использовать по своему усмотрению, например показать картинку. Начиная с версии 2.9.2 появилась третья возможность при [mo=2;]. В этом случае все показывается как в первом случае, но проводится отбор файлов по расширениям. То есть показываются не все файлы, а только те, у которых расширение совпадает с одним из указанного списка. Список расширений нужно задавать как аргумент, причем разные типы файлов разделяются знаком вертикальной черты, вот так txt|bat|mp3\E. Можно указывать только один тип файлов. Такая форма удобна при поиске файлов определенного типа, так как существенно уменьшает каталог и облегчает поиск нужного файла.
Следующие операции относятся к команде файл по той причине, что они реально создают файлы. Но эти файлы имеют специальную природу. Эти операции могут пригодиться только в программах по обработке изображений. Поэтому читатели, которых не интересует эта тема, могут пропустить изучение этих операций. Тем более, что здесь используется специальная информация об изображениях. Кроме того, эти операции реализованы только на ПК, на КПК их нет. Как правило, эти операции используются в блоке с другими командами. После такого введения все же приступим к работе.
#f [op=tobm; file=; form=; dir=; n=; col=;]
Эта операция конвертирует графические файлы с расширениями (gif, jpg, png) в byte-map файлы. Каждый байт такого файла описывает уровень серого от 0 до 255. Параметр [file] должен указывать имя графического файла, например, [file=one.jpg;]. Однако, если [file=here;], то картинка будет считана не из файла, а из оперативной памяти, в которой хранится массив картинок, как элемент с номером [n]. Такая картинка должна быть предварительно записана. В результате операции будет создан новый файл с именем, заданным параметром [form] как графический файл в новом формате. Этот формат нестандартный, некоторые его называют raw (необработанный). При этом, параметр [dir] (direction) определяет направление записи по вертикали. Если [dir=1;], то запись идет в направлении сверху вниз, обычном для графических файлов. Для любого другого значения, например [dir=0;], картинка записывается начиная с нижней строки вверх, как это делается во всех расчетных изображениях. Как обычно, элементы строк картинки записываются подряд. Ширина картинки возвращается в параметр s(12), а высота -- в параметр s(13). Цветные картинки преобразуются в серые по закону скалярного произведения с заданным цветом, номер которого в массиве цветов задает параметр [col]. Пусть этот цвет имеет компоненты R,G,B. Тогда цвет каждого пиксела приводит к уровню серого g по закону g=(r*R+g*G+b*B)/255), но внутри интервала (0,255). Такой способ позволяет применять цветные фильтры при конвертировании картинки, а также менять ее яркость. Информация о цветах будет описана ниже в разделе описания графики. Размер записанного файла в байтах равен числу пикселей в картинке.
#f [op=tocm; file=; form=; dir=; n=;]
Эта операция конвертирует графические файлы с расширениями (gif, jpg, png) в color-map файлы. Каждые три байта такого файла описывают уровень красного, зеленого и синего от 0 до 255 для одной точки рисунка (пиксела). Параметр [file] указывает имя графического файла, например, [file=one.jpg;]. Однако, если [file=here;], то картинка будет считана из оперативной памяти из массива картинок как элемент с номером [n]. Такая картинка должна быть предварительно записана. В результате будет создан новый файл с именем, заданным параметром [form] как графический файл в новом формате. При этом, параметр [dir] определяет направление записи по вертикали. Если [dir=1;], то запись идет в направлении сверху вниз, обычном для графических файлов. Для любого другого значения, например [dir=0;], картинка записывается начиная с нижней строки вверх, как это делается во всех расчетных изображениях. Как обычно, элементы строк картинки записываются подряд, три цвета на каждый элемент. Ширина картинки возвращается в параметр s(12), а высота в параметр s(13). Размер записанного файла в байтах равен утроенному числу пикселей в картинке.
#f [op=tops; mo=; uni=; file=; form=; n=;]
Эта операция конвертирует графические файлы с расширениями (gif, jpg, png) в EPS файлы (encapsulated postscript file). Параметр [file] должен указывать имя графического файла, например, [file=one.jpg;]. Однако, если [file=here;], то картинка будет считана из оперативной памяти из массива картинок как элемент с номером [n]. Такая картинка должна быть предварительно записана. В результате операции будет создан новый файл с именем, заданным параметром [form] как графический файл в формате eps. Имя файла указывается вместе с расширением. Оно не обязано иметь расширение eps. При этом параметр [mo] должен быть 0, 1, 2, 3, 4 или 5. Значение 0 приводит к созданию черно-белого eps-файла, значение 2 - к фрагменту этого файла, который описывает картинку. Этот фрагмент можно использовать в команде #ps для создания комбинированной картинки. Значение 1 приводит к созданию цветного eps-файла, значение 3 - к фрагменту этого файла. Значения 4 или 5 описаны ниже. Другие значения приводят к ошибке. Параметр [uni] определяет дополнительно масштабирующий фактор для картинки в режимах [mo=0,1;], чтобы получить соответствие размеров eps-картинки на экране исходной картинке. Этот фактор равен отношению пиксела экрана к PS точке в единицах 0.0001. Например, пусть компьютер имеет 1024 пиксела на размере экрана 28.42 см. Когда используется GSview в режиме увеличения, показывающем бумагу формата A4 (595 точек) на размере экрана 26.4 см, отношение будет 0.6255. С этим значением GhostView показывает картинку точно также, как и vkACL. Однако, это соотношение может быть другим на других компьютерах. Каждый пользователь может определить отношение эмпирическим путем. В моем случае было [uni=6255;]. Иногда очень важно иметь соответствие каждого пиксела каждой точке экрана так как интерполяция приводит к артефактам.
Описанные операции я реализовал сам, используя законные команды языка постскрипт. И они делают eps файл, который нормально показывается программой GSview в комбинации с другим кодом только в том случае, если картинка стоит последней. Причина в том, что код записан без учета особенности компьютера считывать данные из файла кусками заданных размеров. Если за картинкой стоит какой-то код, то он может быть потерян при такой системе считывания. Соответственно невозможно комбинировать две eps картинки в одной, а также могут быть проблемы при использовании картинки в Латехе. Иногда все получается, но не всегда. По этой причине летом 2009 года я добавил две новые операции 4 и 5, код которых я заимствовал из чужой программы. При этом операция 4 делает полный eps файл, а операция 5 -- фрагмент. Этот код написан несколько другим способом, он более стабилен и не зависит от того, как считывается файл. Поэтому он всегда нормально работает при любых комбинациях постскрипт кода. Данный код всегда делает цветную картинку, соответственно размер файла получается большим. Но у него есть особенность. Если картинка имеет фиксированное число цветов меньше 256, то код использует карту цветов, что позволяет существенно сократить размеры eps файла. Понизить цветность картинки можно с помощью программы Fast Stone Viewer.
Здесь уместно отметить, что полная версия интерпретатора выполняет команду #pd, которая позволяет конвертировать большой спектр графических форматов в pdf-формат. Это также делается специальной библиотекой Java-классов, написанной другими авторами.
#f [op=topng; form=; n=;]
Эта операция конвертирует графические картинки, записанные предварительно в памяти компьютера, в файл png-формата. Запись картинок в память компьютера проводят графические команды #w #g #eg . Сами эти команды способны конвертировать картинки в файл jpg-формата. Но jpg-формат не всегда подходит для линейной графики. Файлы получаются неоправданно больших размеров, а линии окружены заметным грязным фоном, обусловленным алгоритмом jpeg-сжатия. В этом случае разумно спасать созданные картинки в память и затем конвертировать в png-файл с помощью указанной операции. Здесь параметр [form] указывает имя файла без расширения, который будет записан. Расширение всегда ".png". Параметр [n] указывает номер картинки, спасенной предварительно в памяти. Если картинка не существует, будет выдано сообщение об ошибке. Эта операция сделана для универсальности. Так как картинки создают несколько команд, то реализация в каждой команде записи в файлы разных форматов приводит к увеличению кода и сложной структуре параметров.
#f [op=w2jc; file=;]
Эта операция имеет специальный характер, она может пригодиться при использовании программ, написанных на разных языках программирования. Дело в том, что файлы в компьютерном коде float (4 байта на одно реальное число) записываются в ACL программах так же, как в Java или в любой программе системы UNIX, то есть старшие байты слева, младшие справа. Однако в системе Windows принят обратный порядок - младшие байты слева. Поэтому для того, чтобы ACL программа могла правильно прочитать файл, записанный любой программой в системе Windows (например, написанной на фортране), необходимо переставить порядок байтов в каждом числе. Именно это и делает данная операция. Она прочитывает файл, переставляет в нем байты и новое содержание записывает на старое место. Повторное применение операции все возвращает на исходные позиции. Таким образом, эта операция позволяет как использовать результаты Windows программ в ACL, так и результатов ACL в Windows программах.
#f [op=alph;] FT FT
Эта операция тоже имеет специальный характер. Она считывает текст из файла, полный путь к которому должен быть указан первым аргументом FT. Затем она упорядочивает все строки в тексте по алфавиту и новый текст записывает в файл, полный путь к которому указан вторым аргументом FT. Если оба файла находятся в той же папке, что и ACL программа, то полный путь определяется легко с помощью команд печати \M\H/имя файла. Если в начале каждой строки ставить номера, то операция упорядочивает строки по номерам. Если в каждой строке набито только одно слово, то операция упорядочивает слова по алфавиту.