Глава 14 - Порты
Руководство пользователя REBOL/Core Основное содержание Отправьте нам отзыв
Содержание:
1. Обзор
2. Открытие порта
2.1 Функция открытия
2.2 Открытые уточнения
3. Закрытие порта
4. Чтение из порта
5. Запись в порт
6. Обновление порта
7. Ожидание порта
8. Другие режимы порта
8.1 Линейный режим
8.2 Только чтение и запись
8.3 Прямой доступ к портам
8.4 Пропуск данных
9. Права доступа к файлам
10. Порты каталогов
1. Обзор
Порты обращаются к внешним (external) сериям, таким как файлы, сети, консоли, события, базы данных, кодировщики данных и декодеры данных. Данные порта обрабатываются с использованием стандартных функций серии REBOL, как описано в главе «Серии».
Порты используются как для ввода, так и для вывода. Тип данных, которые обрабатывает порт, зависит от того, как порт открыт. Возможны три типа данных:
| | String | серия байтов, преобразует разрывы строк (по умолчанию)
|
| | Binary | серия байтов, без преобразования данных
|
| | Block | серия значений REBOL
|
Порт можно открыть в одном из двух режимов буферизации:
| | Buffered | все данные хранятся в памяти (по умолчанию)
|
| | Direct | данные не хранятся в памяти
|
Кроме того, порт можно открыть с помощью:
| | Wait | порт будет ждать данных (по умолчанию)
|
| | No-wait | порт не будет ждать данных
|
2. Открытие порта
2.1 Функция открытия
Функция open инициализирует доступ к порту в соответствии с указанными параметрами. Функция может быть снабжена именем файла, URL-адресом или объектом. Кроме того, есть несколько уточнений, которые повлияют на операцию открытия или доступ к данным порта.
Самый простой способ использования open - предоставить ему имя файла или URL в качестве аргумента. В приведенном ниже примере открывается файловый порт:
fp: open %file.txt
FP переменная относится к порту. Если порт не открылся, произойдет ошибка. При необходимости ошибку можно отловить с помощью функции try.
По умолчанию файл открывается как буферизованный. Это означает, что к файлу осуществляется доступ и модифицируется в памяти, и изменения в файл не записываются, пока порт не будет закрыт или обновлен.
Для файлов функция open автоматически создаст файл, если он еще не существует.
close open %somefile.txt
if exists? %somefile.txt [print "somefile exists"]
somefile exists
Уточнение /new может быть использовано для перезаписи существующего файла.
write %somefile.txt "text in some file"
print read %somefile.txt
text in some file
close insert open/new %somefile.txt "new data"
print read %somefile.txt
new data
После того, как порт открыт, последовательные операции, такие как копирование (copy), вставка (insert), удаление (remove), очистка (clear), первый (first), следующий (next) и длина? (length?) может использоваться для доступа и изменения содержимого порта.
2.2 Уточнения функции open
Функция open принимает ряд уточнений, которые можно использовать для изменения ее работы:
| | /binary | данные порта являются двоичными
|
| | /string | данные порта - текст, перевод всех символов окончаний строк
|
| | /with | указать альтернативное завершение строки
|
| | /lines | обрабатывать данные построчно или как блок строк
|
| | /direct | не буферизировать порт
|
| | /new | создать или воссоздать цель порта
|
| | /read | открыт для операции только для чтения
|
| | /write | открыт только для записи
|
| | /no-wait | не ждать данных
|
| | /skip | пропустить часть данных
|
| | /allow | указать атрибуты защиты файлов
|
| | /custom | разрешить особые уточнения
|
3. Закрытие порта
Доступ к порту завершается функцией close (закрыть). Все несохраненные буферизованные данные будут записаны в целевой файл. В приведенном ниже примере будет закрыт порт, открытый ранее:
close fp
Если вы попытаетесь закрыть закрытый порт, произойдет ошибка.
Закрытый порт можно снова открыть с помощью функции open:
open fp
4. Чтение из порта
Функция copy используется для чтения данных из открытого порта:
print copy fp
I wanted the gold, and I sought it,I scrabbled and mucked like
a slave....
Эта функция будет ждать данных порта. Если вы не хотите ждать данных, откройте порт с уточнением /no-wait.
Чтобы прочитать только часть данных порта, используйте copy/part:
print copy/part fp 35
I wanted the gold, and I sought it,
Обратите внимание, что вторым аргументом для копирования может быть длина или позиция в порту.
Вы можете использовать функции поиска (find) и копирования (copy) серий, чтобы прочитать только часть данных порта:
a: find fp "famine"
print copy/part a find a newline
famine or scurvy -- I fought it;
В порте также могут использоваться функции first, next и другие позиционные последовательные функции:
print first fp
I
print first next next fp
w
Функция copy не вернет none, когда все данные будут прочитаны из порта. Когда не работает в /no-wait режима, то функция copy возвращает пустую строку, если нет данных для порта.
tp: open/direct/binary/no-wait tcp://system:8000
content: make binary! 1000
while [wait tp data: copy tp] [append content data]
close tp
5. Запись в порт
Функция вставки (insert ) используется для записи в порт.
insert fp "I was a fool to seek it."
Если порт находится в буфере, изменение будет происходить извне, когда порт будет закрыт или обновлен (с функцией update). Если порт открыт с помощью /direct, изменение произойдет немедленно.
Все уточнения функции insert могут быть использованы для порта. Например, чтобы записать в порт 20 пробелов:
insert/dup fp " " 20
Вы также можете использовать для порта функции remove (удаления), clear (очистки), change (изменения), append (добавления), replace (замены) и другие функции изменения серии.
Например, чтобы удалить один символ или несколько символов:
remove fp
remove/part fp 20
и чтобы удалить все оставшиеся символы, напишите:
clear fp
6. Обновление порта
Функция update заставляет порт обновлять свой статус по отношению к внешнему устройству. Например, при записи буферизованного файла функцию обновления можно использовать для принудительного вывода буфера данных в файл. При чтении можно использовать функцию update, чтобы быть уверенным, что все ожидающие данные были прочитаны в память.
update fp
7. Ожидание порта
Функция wait (ожидание) важна для программ, которым необходимо обрабатывать асинхронную передачу данных. С помощью wait вы можете дождаться данных на одном или нескольких портах или истечения времени ожидания.
Функция wait принимает один порт:
wait port
или может быть предоставлен целый блок портов:
wait [port1 port2 port3]
Кроме того, значение тайм-аута может быть указано в секундах или в виде значения времени:
wait [port1 port2 10]
wait [port1 port2 0:00:05]
В первом примере время ожидания истекает через десять секунд. Во втором примере тайм-аут будет через пять секунд.
Функция wait вернет порт, который готов или none, если истекло время ожидания.
ready: wait [port1 port2 10]
if ready [data: copy ready]
В приведенном выше примере данные будут считываться из первого готового порта, если тайм-аут не наступил.
Чтобы получить блок всех готовых портов, используйте уточнение /all.
ready: wait/all [port1 port2 10]
if ready [
foreach port ready [
append data copy port
]
]
В этом примере данные со всех готовых портов будут добавлены в одну серию.
Вы также можете использовать функцию отправки (dispatch) для оценки блока или функции на основе результатов ожидания (wait) на нескольких портах.
dispatch [
port1 [print "port1 awake"]
port2 [print "port2 awake"]
10 [print "timeout!"]
]
Используйте /No-wait и /Direct
Чтобы использовать wait с большинством портов, вам нужно будет указать уточнения / no-wait и / direct как часть open. Это указывает на то, что обычные функции доступа к данным не должны блокироваться и что данные не буферизуются.
port1: open/no-wait/direct tcp://system:8000
8. Другие режимы порта
8.1 Линейный режим
Функция open позволяет открывать порты для линейного доступа. В строчном режиме первая функция вернет строку текста, а не символ. В приведенном ниже примере файл читается по одной строке за раз:
fp: open/lines %file.txt
print first fp
I wanted the gold, and I got it --
print third fp
Yet somehow life's not what I thought it,
Уточнение /lines также полезно для интернет-протоколов, ориентированных на линию (строк).
tp: open/lines tcp://server:8000
print first tp
8.2 Только чтение и запись
Вы можете использовать уточнение /read, чтобы открыть порт только для чтения:
fp: open/read %file.txt
Изменения, внесенные в буфер порта, не записываются обратно в файл.
Чтобы открыть только для записи, используйте уточнение /write:
fp: open/write %file.txt
Файловые порты, открытые с уточнением /write, не будут читать текущие данные при открытии порта.
Закрытие или обновление файлового порта только для записи приведет к перезаписи существующих данных в файле:
insert fp "This is the law of the Yukon..."
close fp
print read %file.txt
This is the law of the Yukon...
8.3 Прямой доступ к порту
Уточнение /direct открывает небуферизованный порт. Это полезно для доступа к файлам по частям, например, когда файл слишком велик для хранения в памяти.
fp: open/direct %file.txt
Чтение данных с помощью функции copy переместит голову указателя порта вперед:
print copy/part fp 40
I wanted the gold, and I sought it,^/ I
print copy/part fp 40
scrabbled and mucked like a slave.^/Was i
В прямом режиме указатель порт всегда будет в исходном положении:
print head? fp
true
Функция copy вернет none, когда порт достигнет своего конца.
Вот пример, который использует прямые порты для копирования файла любого размера:
from-port: open/direct %a-file.jpg
to-port: open/direct %a-file.jpg
while [data: copy/part from-port 100000 ][
append to-port data
]
close from-port
close to-port
8.4 Пропуск данных
Есть два способа пропустить данные, существующие в порту. Во-первых, вы можете открыть порт с уточнением /skip. Эта функция open автоматически перейдет к определенной точке порта. Например:
fp: open/direct/skip %file.big 1000000
fp: open/skip http://www.example.com/bigfile.dat 100000
Вы также можете использовать функцию skip порта. Для файлов, которые открываются с помощью /direct и /binary, операция пропуска идентична операции поиска в файловой системе. Данные не считываются в память. Это невозможно в режиме /string, потому что разрывы строк влияют на размер пропуска.
fp: open/direct/binary %file.dat
fp: skip fp 100000
9. Права доступа к файлам
Когда файлы создаются REBOL, устанавливаются права доступа по умолчанию. В системах Windows и Macintosh файлы создаются с правами полного доступа. В системах UNIX файлы создаются с разрешениями, установленными на текущую настройку umask.
При использовании open или write для доступа к файлу уточнение /allow используется для установки разрешений на доступ к файлу.
Уточнение /allow принимает блок в качестве аргумента. Этот блок может состоять из любого или всех трех слов read,
write и execute.
Ограничения операционной системы
Уточнение /allow только установить разрешения на операционных системах , поддерживающих заданную настройку разрешений. Если операционная система не поддерживает используемый параметр разрешений, он будет проигнорирован. Например, файлы в системах UNIX могут быть установлены как исполняемые (execute), но операционные системы Windows и Macintosh не поддерживают это. При работе с системами UNIX разрешения, установленные с помощью /allow, будут устанавливать только права пользователя. Использование /allow приведет к удалению всех прав доступа для пользователей и других лиц.
Чтобы сделать файл доступным только для чтения, используйте open/allow или write/allow с блоком чтения.
write/allow %file.txt [read]
Чтобы сделать файл читаемым и исполняемым:
open/allow %file.txt [read execute]
Вы можете установить аналогичные разрешения для доступа на запись:
write/allow %file.txt [read write]
Чтобы предотвратить любой доступ к файлу (для операционных систем, где это имело бы значение), предоставьте пустой блок разрешений:
write/allow %file.txt []
Чтобы разрешить полный доступ:
write/allow %file [read write execute]
10. Порты каталогов
Порты каталогов позволяют открывать прямой доступ к каталогам файлов. В системе именно так создается большинство других функций каталогов.
Когда вы открываете каталог, вы получаете прямой доступ к нему в виде блока имен файлов:
mydir: open %intro/
forall mydir [print first mydir]
CVS/
history.t
intro.t
overview.t
quick.t
close mydir
Вы можете перейти к определенной позиции в серии каталогов и удалить файл с таким кодом, как:
dir: open %.
remove next dir
close dir
Это удаляет второй файл в текущем каталоге. По аналогии,
remove at dir 5
удалит пятый файл в каталоге и:
clear dir
удалит все файлы в каталоге.
Чтобы удалить все файлы, содержащие слово "junk", вы можете написать:
dir: open %intro/
while [not tail? dir] [
either find first dir "junk" [remove dir][
dir: next dir
]
]
close dir
Изменения, внесенные в каталог, производятся при закрытии каталога или при его обновлении. Чтобы действие было выполнено немедленно, используйте такую строку, как:
update dir
Метод доступа к каталогам также может использоваться для изменения имен файлов. После open строка:
change at dir 3 %newname.txt
переименует третий файл в каталоге. Аналогичным образом можно изменить имена любого из файлов в каталоге.
Вот пример, который переименовывает все файлы в каталоге, добавляя слово REBOL к их именам:
dir: open %intro/
forall dir [insert first dir "REBOL"]
close dir
|