Tcl-файлы, чем открывать

Обновлено: 01.07.2024

Чтение текстового файла в строку:

JCW: Просто из любопытства. будет ли приведенный ниже минимальный код эквивалентным, т. е. действительно ли закрытие выполняется автоматически в этом контексте?

RS: По словам человека близкого, "Каналы автоматически закрываются, когда интерпретатор уничтожается и когда процесс завершается". Из этого я подразумеваю, что они не закрываются автоматически в другом месте. Дескриптор файла, открытого для чтения, не может причинить большого вреда, кроме утечки памяти (и может привести к тому, что у приложения закончатся доступные файловые дескрипторы). В любом случае, я применил простое правило: это" ;-)

JCW: Да, хорошо, но разве файл не закрывается, когда (и потому что) исчезает последняя ссылка? Или компиляция байт-кода влияет на это и приводит к сохраненной ссылке? Пытливые умы хотят знать. :о)

Винс: В интерпретаторе есть ссылка (по файловым каналам). Единственный способ избавиться от этой ссылки — закрыть (если только вы не прибегаете к коду C).

Арьен Маркус: Существует веская причина, по которой файл не закрывается автоматически (та же, я думаю, что и с любым другим языком программирования): вы можете захотеть сделать с файлом больше, например добавить в конец, заменить содержимое и так далее.

Минимальная процедура может быть даже короче:

так как по умолчанию чтение потребляет все доступное.

RS: Да, но с использованием размера буфера по умолчанию, который может работать медленнее. Много лет назад меня учили, что для повышения производительности всегда следует указывать размер файла.

Стивен Триер: Я тоже так думал, но JH говорит на c.l.t, что это уже неправда. Его результаты TclBench (Tcl Normalized Benchmarks) подтверждают это.

Однострочник, который не оставляет файлы открытыми, можно сделать с помощью комбинатора K. (Глоссарий терминов)

Тео Верелст: Мне было бы интересно узнать, возвращается ли чтение вообще или в течение гарантированного интервала времени с действительным файлом, в разновидностях Unix, потому что он может быть обновлен во время чтения, и в Windows, ну, эх, что-то может случиться к нему всегда.

Независимо от того, закрою ли я его или интерпретатор. И затем я хотел бы знать, какую версию я получил, и будут ли программы, обращающиеся к ней, блокироваться из-за таких соображений, то есть, возможно, конструкция open/close служит потенциальной цели в таком мышлении.

dizzy: однострочник, которому не нужен комбинатор K:

Прикоснитесь к файлу: без изменения содержимого измените время доступа к файлу на (сейчас); создайте его, если он не существует, с содержимым 0 байт:

Почему бы просто не использовать

RS: В очень новых версиях файл mtime можно использовать со вторым аргументом для установки mtime; но не в 8.2.3.

CL: ясно показывает, что, хотя новички в Tcl из лучших побуждений часто думают, например, в терминах,

приведенные выше формы более переносимы, безопасны, сохраняют производительность.

LV: со всеми исправлениями ошибок, которые произошли после Tcl 8.2.3, я надеюсь, что люди скоро перейдут на 8.3.4.

RS: На самом деле я использую 8.3.4 (даже сам скомпилировал ее ;-), но мой Winhelp все еще 8.2.3. Но я не спешу гнаться за последними версиями — мы тут ставим Cygwins, которые еще на 8.0.4, поэтому наши скрипты не могут быть слишком требовательными. Кроме того, файл mtime .. работает только с существующими файлами. Чтобы иметь полную «сенсорную» функциональность (создайте, если не существует), файл close [open . ] подход лучше.. и короче (словами) тоже ;-)

LV: Тем не менее, закрытие/открытие имеет недостаток, заключающийся в том, что у него нет реальной сенсорной функции и возможности установить время модификации на любое желаемое время - какой файл mtime имеет.

Определить, является ли файл «двоичным», т. е. содержит ли он хотя бы один байт NUL (после подсказки Донала Феллоуза c.l.t):

Еще одна версия с ремнем и подтяжками, полученная из той же темы: дискриминатор двоичных файлов isBinary

Арьен Маркус: Часто я читаю файлы данных, как если бы они были просто еще одним исходным файлом Tcl (через источник. Это может привести к проблемам, если специальные символы, такие как [ и ], являются частью содержимого. Существует ли общая стратегия? для обхода этого? (Предыстория такова, что в одном приложении исходные файлы состоят из смеси фрагментов кода Tcl и C/Java/., поэтому они усеяны специальными символами, которые являются особыми по-разному. У меня есть решение, но что-то не совсем правильно.)

RS: Трудно сказать в таком обобщении. Tcl такой динамичный, с каждым процессом или около того вы меняете язык, и гораздо глубже с неизвестным. Вы можете перехватить ненадежные файлы в безопасный интерпретатор, чтобы предотвратить хаос, и заставить этот интерпретатор вернуть вам нужные данные (таким образом отфильтровывая возможные другие побочные эффекты).

Бенни Рифеншталь: list выполняет работу по цитированию содержимого во всех случаях, которые необходимы для динамического создания безопасного кода. Я обычно делаю постоянство как

Подсчет строк в одном или нескольких файлах:

Пример использования: wc-l [glob *.tcl]

Прочитать строку, указанную по ее номеру, из текстового файла:

Существует множество способов улучшить эту процедуру — например, сохранить номер строки из предыдущего вызова в глобальной переменной и выполнять поиск в начале только в том случае, если нужная строка меньше текущей. (из сообщения c.l.t Виктора Вагнера)

JPTanguay: однострочник, использующий внешние команды:

Арьен Маркус: Моя любимая техника в настоящее время – использование промежуточных псевдонимов . Вы можете хранить скрытые аргументы таким образом, и нет необходимости засорять глобальное пространство имен. Пример см. в разделе Сборка мусора.

Найти исполняемый файл из переменной среды PATH:

Обратите внимание, что это ядро ​​команды auto_execok, предопределенной в библиотеке скриптов tcl.

AK: За исключением того, что в качестве разделителя всегда используется ":".

RS: Судя по тому, что я вижу, довольно постоянно ";" - весь auto_execok выглядит немного ориентированным на Windows. но он выполняет работу, для которой я написал выше, поэтому более минимально (= лучше) использовать auto_execok. Спасибо!

Завершение строки файла:

CR и/или LF? Донал Феллоуз показывает путь:

Lars H 27 февраля 2003 г.: вместо того, чтобы определять, что является ограничителем строки в указанном файле, определите, что Tcl считает ограничителем строки? Отвечая самому себе 9 сентября 2004 г.: Да, это так, но по умолчанию файлы чтения Tcl обрабатывают все lf, cr и crlf как завершение строки, так что вы действительно получаете нужную информацию о том, какой из них из этих трех он находится в этом файле.

Чтение файлов:

принимает имя файла, возвращает строки этого файла в виде списка. Тривиальный алгоритм, но обратите внимание на «белый сахар»: упоминания переменной выровнены по вертикали, чтобы указать на поток данных ;-)

Нормализовать окончания строк в текстовом файле. Программное обеспечение, отличное от Tcl, может иметь всевозможные проблемы, когда текстовые файлы редактировались на другой платформе, поскольку окончания строк иногда бывают CR-LF, иногда LF, иногда CR, а некоторые редакторы нормализуют часть из них, а другие нет. Tcl читает строки в соответствии с любым соглашением и записывает в соответствии с местным соглашением, поэтому эта простая процедура помогает там, где даже dos2unix не работает:

Определить длину последовательности EOL:

MG просто нужно было узнать, какова длина последовательности EOL в конкретном файле. Проверка fconfigure $fid -translation не помогла (поскольку это было просто «авто» при чтении и всегда crlf (Win XP) при записи, даже если в файле использовались окончания строк Unix). Придумал это (что, возможно, очевидно, но я в любом случае доволен собой;)

DKF: Это может пойти не так. Проблема в том, что вам нужно использовать закодированную длину прочитанной строки, а некоторые кодировки имеют несколько способов кодирования определенного символа. Все это довольно противно; даже предположение, основанное на значении fconfigure -encoding, может пойти не так! Вместо этого попробуйте следующее:

MG: Я попробую так, спасибо :)

Разрешить символические ссылки с помощью рекурсии: рекурсия полезна при попытке пройти по серии или цепочке символических ссылок до конечного пункта назначения. Рекурсия останавливается, когда встречается что-то, что не является ссылкой. -CJU

Проверить, открыт ли канал:

Еще одна версия, которая в несколько раз быстрее на каналах, которых больше нет, но немного медленнее на существующих.

Проверить, равны ли два файла (функционально, а с комбинатором K - RS):

Эта команда открывает файл, последовательный порт или конвейер команд и возвращает идентификатор канала, который можно использовать в будущих вызовах таких команд, как read , puts и close . Если первый символ имени файла не | затем команда открывает файл: fileName задает имя открываемого файла, и оно должно соответствовать соглашениям, описанным в ручном вводе имени файла.

Аргумент доступа, если он присутствует, указывает способ доступа к файлу (или конвейеру команд). В первой форме доступ может иметь любое из следующих значений:

r Открыть файл только для чтения; файл должен уже существовать. Это значение по умолчанию, если доступ не указан.

r+ Открыть файл как для чтения, так и для записи; файл должен уже существовать.

w Открыть файл только для записи. Сократите его, если он существует. Если он не существует, создайте новый файл.

w+ Открыть файл для чтения и записи. Сократите его, если он существует. Если он не существует, создайте новый файл.

a Откройте файл только для записи. Если файл не существует, создайте новый пустой файл. Устанавливайте указатель файла в конец файла перед каждой записью.

a+ Открыть файл для чтения и записи. Если файл не существует, создайте новый пустой файл. Установите начальную позицию доступа в конец файла.

Во второй форме доступ состоит из списка любых из следующих флагов, все из которых имеют стандартные значения POSIX. Один из флагов должен быть RDONLY , WRONLY или RDWR .

RDONLY Открыть файл только для чтения.

ОШИБОЧНО открыть файл только для записи.

RDWR Открыть файл для чтения и записи.

APPEND Устанавливает указатель файла в конец файла перед каждой записью.

CREAT Создать файл, если он еще не существует (без этого флага отсутствие файла является ошибкой).

EXCL Если также указано CREAT, возвращается ошибка, если файл уже существует.

NOCTTY Если файл является терминальным устройством, этот флаг предотвращает превращение файла в управляющий терминал процесса.

NONBLOCK Предотвращает блокировку процесса при открытии файла и, возможно, при последующих операциях ввода-вывода. Точное поведение этого флага зависит от системы и устройства; его использование не рекомендуется (лучше использовать команду fconfigure, чтобы перевести файл в неблокирующий режим). Подробнее см. в системной документации по флагу O_NONBLOCK открытого системного вызова.

TRUNC Если файл существует, он усекается до нулевой длины.

Если новый файл создается как часть его открытия, разрешения (целое число) используются для установки разрешений для нового файла в сочетании с маской создания режима файла процесса. Разрешения по умолчанию равны 0666.

Обратите внимание, что если вы собираетесь считывать или записывать двоичные данные из канала, созданного этой командой, вам следует использовать команду fconfigure, чтобы изменить параметр -translation канала на двоичный перед передачей любых двоичных данных. Это отличается от символа ``b'', который передается как часть эквивалента параметра доступа к некоторым версиям функции fopen() из библиотеки C.

Если первым символом fileName является ``|'', то остальные символы fileName обрабатываются как список аргументов, описывающих вызываемый конвейер команд, в том же стиле, что и аргументы для exec . В этом случае идентификатор канала, возвращаемый open, может использоваться для записи во входной канал команды или чтения из выходного канала, в зависимости от значения access. Если используется доступ только для записи (например, доступ — это w ), то стандартный вывод для конвейера направляется на текущий стандартный вывод, если он не переопределен командой. Если используется доступ только для чтения (например, доступ r ), стандартный ввод для конвейера берется из текущего стандартного ввода, если только команда не переопределяет его. Идентификатор порожденного процесса доступен через команду pid, используя идентификатор канала, возвращаемый open в качестве аргумента.

Если команда (или одна из команд), выполненная в командном конвейере, возвращает ошибку (в соответствии с определением в exec ), при вызове close на канале генерируется ошибка Tcl, если только конвейер не находится в неблокирующем состоянии. режиме, то статус выхода не возвращается (тихое закрытие с -blocking 0).

Часто полезно использовать команду fileevent с конвейерами, чтобы другая обработка могла выполняться одновременно с выполнением команды в фоновом режиме.

Если имя_файла относится к последовательному порту, то указанный последовательный порт открывается и инициализируется в зависимости от платформы. Допустимые значения имени файла, используемые для открытия последовательного порта, описаны в разделе ПРОБЛЕМЫ ПЕРЕНОСИМОСТИ.

Команду fconfigure можно использовать для запроса и установки дополнительных параметров конфигурации, характерных для последовательных портов (где они поддерживаются):

-mode baud , parity , data , stop Этот параметр представляет собой набор из 4 значений, разделенных запятыми: скорость передачи, четность, количество битов данных и количество стоповых битов для этого последовательного порта. Скорость передачи — это простое целое число, указывающее скорость соединения. Четность — это одна из следующих букв: n, o, e, m, s; соответственно обозначая параметры четности «нет», «нечетный», «четный», «отметить» или «пробел». Данные — это количество бит данных, которое должно быть целым числом от 5 до 8, а стоп — это количество стоповых битов, которое должно быть целым числом 1 или 2.

-тип рукопожатия (Windows и Unix). Эта опция используется для настройки автоматического управления рукопожатием. Обратите внимание, что не все типы рукопожатий могут поддерживаться вашей операционной системой. Параметр типа не зависит от регистра.

Если type не установлен, любое рукопожатие отключено. rtscts активирует аппаратное рукопожатие. Аппаратные сигналы квитирования описаны ниже. Для программного рукопожатия xonxoff символы рукопожатия можно переопределить с помощью -xchar . Дополнительное аппаратное рукопожатие dtrdsr доступно только под Windows. Конфигурации рукопожатия по умолчанию нет, начальное значение зависит от настроек вашей операционной системы. Параметр -handshake не может быть запрошен.

-queue (Windows и Unix). Параметр -queue можно только запрашивать. Он возвращает список из двух целых чисел, представляющих текущее количество байтов во входной и выходной очереди соответственно.

-timeout msec (Windows и Unix). Этот параметр используется для установки тайм-аута для блокировки операций чтения. Он указывает максимальный интервал между приемом двух байтов в миллисекундах. Для систем Unix степень детализации составляет 100 миллисекунд. Параметр -timeout не влияет на операции записи или неблокирующего чтения. Этот параметр не может быть запрошен.

-ttystatus (Windows и Unix).Параметр -ttystatus можно только запрашивать. Он возвращает текущее состояние модема и входные сигналы квитирования (см. ниже). Результатом является список пар сигнал-значение с фиксированным порядком, например. . Имена сигналов возвращаются в верхнем регистре.

-pollinterval мсек (только для Windows). Эта опция используется для установки максимального времени между опросом файловых событий. Это влияет на временной интервал между проверками событий во всем интерпретаторе Tcl (наименьшее значение всегда имеет преимущество). Используйте этот параметр, только если вы хотите опрашивать последовательный порт чаще или реже, чем 10 мс (по умолчанию).

-lasterror (только для Windows). Этот параметр предназначен только для запроса. В случае ошибки последовательной связи read или puts возвращает общую ошибку ввода-вывода файла Tcl. Можно вызвать fconfigure -lasterror, чтобы получить список сведений об ошибках. Ниже приведены пояснения к различным кодам ошибок.

RS-232 — это наиболее часто используемый стандартный электрический интерфейс для последовательной связи. Отрицательное напряжение (-3В..-12В) определяет метку (вкл=1) бит, а положительное напряжение (+3..+12В) определяет пробел (выкл=0) бит (RS-232C). Следующие сигналы указаны для входящих и исходящих данных, строк состояния и квитирования. Здесь мы используем термины рабочая станция для вашего компьютера и модем для внешнего устройства, потому что некоторые названия сигналов (DCD, RI) происходят от модемов. Конечно, ваше внешнее устройство может использовать эти сигнальные линии для других целей.

TXD (выход) Передаваемые данные: исходящие последовательные данные.

RXD(input) Полученные данные: входящие последовательные данные.

Запрос RTS (выходной) на отправку: Эта аппаратная линия квитирования информирует модем о том, что ваша рабочая станция готова к приему данных. Ваша рабочая станция может автоматически сбрасывать этот сигнал, чтобы указать, что входной буфер заполнен.

CTS(input) Clear To Send: Дополнение к RTS. Указывает, что модем готов к приему данных.

DTR (выходной) Терминал данных готов: Этот сигнал сообщает модему, что рабочая станция готова установить соединение. DTR часто включается автоматически при открытии последовательного порта.

Готовый набор данных DSR (входной): дополнение к DTR. Сообщает рабочей станции, что модем готов установить соединение.

DCD(input) Data Carrier Detect: Эта линия становится активной, когда модем обнаруживает сигнал "Carrier".

Индикатор звонка RI(input): становится активным, когда модем обнаруживает входящий вызов.

BREAK Состояние BREAK — это не аппаратная сигнальная линия, а логический ноль на линиях TXD или RXD в течение длительного периода времени, обычно от 250 до 500 миллисекунд. Обычно принимаемый или передаваемый сигнал данных остается на отметке (on=1) напряжения до тех пор, пока не будет передан следующий символ. ПЕРЕРЫВ иногда используется для сброса линии связи или изменения режима работы коммуникационного оборудования.

Во время операций последовательного чтения или во время опроса событий в фоновом режиме может возникнуть множество различных ошибок. Возможно, внешнее устройство было выключено, линии передачи данных могут быть зашумлены, системные буферы могут быть переполнены или ваши настройки режима могут быть неправильными. Вот почему надежное программное обеспечение всегда должно перехватывать операции последовательного чтения. В случае ошибки Tcl возвращает общую ошибку ввода/вывода файла. Тогда fconfigure -lasterror может помочь найти проблему. Могут быть возвращены следующие коды ошибок.

RXOVER Переполнение входного буфера Windows. Данные приходят быстрее, чем ваши скрипты их считывают или ваша система перегружена. Используйте fconfigure -sysbuffer, чтобы избежать временных узких мест и/или ускорить скрипт.

TXFULL Выходной буфер Windows переполнен. Дополнение к RXOVER. Этой ошибки практически не должно быть, потому что Tcl заботится о состоянии выходного буфера.

OVERRUN Переполнение буфера UART (аппаратное обеспечение) с потерей данных. Данные приходят быстрее, чем их получает системный драйвер. Проверьте дополнительные настройки последовательного порта, чтобы включить буфер FIFO (16550) и/или установить более низкое (1) пороговое значение прерывания.

RXPARITY Ваш UART обнаружил ошибку четности. Эта ошибка может быть вызвана неправильными настройками четности с помощью fconfigure -mode или зашумленной линией передачи данных (RXD).

FRAME Ваш UART обнаружил ошибку стопового бита. Эта ошибка может быть вызвана неправильными настройками режима с помощью fconfigure -mode или зашумленной линией передачи данных (RXD).

BREAK Состояние BREAK было обнаружено вашим UART (см. выше).

Windows (все версии) Допустимые значения для имени файла для открытия последовательного порта имеют форму com X : , где X — число, обычно от 1 до 4. Эта запись работает только для последовательных портов от 1 до 9, если в системе их больше четырех. Попытка открыть последовательный порт, который не существует или имеет номер больше 9, потерпит неудачу. Альтернативной формой открытия последовательных портов является использование имени файла \\.\comX , где X — любое число, соответствующее последовательному порту; обратите внимание, что этот метод значительно медленнее в Windows 95 и Windows 98.

Windows NT При интерактивном запуске Tcl возможны странные взаимодействия между реальной консолью, если таковая имеется, и конвейером команд, который использует стандартный ввод или вывод. Если командный конвейер открыт для чтения, некоторые из строк, введенных с консоли, будут отправлены в командный конвейер, а некоторые — в оценщик Tcl. Если конвейер команд открыт для записи, нажатия клавиш, введенные в консоль, не видны до тех пор, пока конвейер не будет закрыт. Это происходит независимо от того, выполняет ли конвейер команд 16-разрядные или 32-разрядные приложения. Эти проблемы возникают только потому, что и Tcl, и дочернее приложение одновременно конкурируют за консоль. Если конвейер команд запускается из скрипта, так что Tcl не обращается к консоли, или если конвейер команд не использует стандартный ввод или вывод, а перенаправляется из файла или в файл, то вышеуказанные проблемы не возникают.< /p>

Windows 95 Конвейер команд, который выполняет 16-разрядное приложение DOS, не может быть открыт одновременно для чтения и записи, поскольку 16-разрядные приложения DOS, которые получают стандартный ввод из канала и отправляют стандартный вывод в канал, выполняются синхронно. Конвейеры команд, которые не выполняют 16-разрядные приложения DOS, работают асинхронно и могут быть открыты как для чтения, так и для записи.

При интерактивном запуске Tcl возможны некоторые странные взаимодействия между реальной консолью, если она присутствует, и конвейером команд, который использует стандартный ввод или вывод. Если командный конвейер открыт для чтения из 32-разрядного приложения, некоторые нажатия клавиш, введенные в консоли, будут отправлены в командный конвейер, а некоторые — в оценщик Tcl. Если конвейер команд открыт для записи в 32-разрядное приложение, вывод не будет отображаться на консоли до тех пор, пока конвейер не будет закрыт. Эти проблемы возникают только потому, что и Tcl, и дочернее приложение одновременно конкурируют за консоль. Если конвейер команд запускается из скрипта, так что Tcl не обращается к консоли, или если конвейер команд не использует стандартный ввод или вывод, а перенаправляется из файла или в файл, то вышеуказанные проблемы не возникают.< /p>

Независимо от того, запущен Tcl в интерактивном режиме или нет, если командный конвейер открыт для чтения из 16-разрядного приложения DOS, вызов open не вернется до тех пор, пока из стандартного вывода командного конвейера не будет получен конец файла. Если командный конвейер открыт для записи в 16-разрядное приложение DOS, никакие данные не будут отправлены на стандартный вывод командного конвейера до тех пор, пока канал не будет фактически закрыт. Эта проблема возникает из-за того, что 16-разрядные приложения DOS запускаются синхронно, как описано выше.

Unix Допустимые значения для fileName для открытия последовательного порта обычно имеют форму /dev/tty X , где X — это a или b , но можно использовать имя любого псевдофайла, который отображается на последовательный порт. Расширенные параметры конфигурации поддерживаются только для последовательных портов, если Tcl создан для использования последовательного интерфейса POSIX.

При интерактивном запуске Tcl возможны некоторые странные взаимодействия между консолью, если она присутствует, и конвейером команд, который использует стандартный ввод. Если командный конвейер открыт для чтения, некоторые из строк, введенных с консоли, будут отправлены в командный конвейер, а некоторые — в оценщик Tcl. Эта проблема возникает только потому, что и Tcl, и дочернее приложение одновременно конкурируют за консоль. Если конвейер команд запускается из скрипта, так что Tcl не обращается к консоли, или если конвейер команд не использует стандартный ввод, а перенаправляется из файла, то вышеуказанная проблема не возникает.

См. раздел ПРОБЛЕМЫ ПЕРЕНОСИМОСТИ команды exec для получения дополнительной информации, не относящейся к командным конвейерам, о выполнении приложений на различных платформах

open , встроенная команда Tcl, открывает файл или выполняет команду и возвращает имя канала, обеспечивающего доступ к содержимому открытого ресурса.

См. также

Журнал изменений

wb появился в Tcl 8.5. kennykb сообщает в чате, что, по его воспоминаниям, он также был доступен в Tcl 7.3 дней или ранее.

Краткий обзор

Документация

Описание

Если добавить b к mode, это будет иметь тот же эффект, что и fconfigure . двоичный файл перевода

Примеры

Одним из вариантов приведенного выше примера fd8, который может быть полезен для отладки, является

В дополнение к запуску simple2 в качестве асинхронного дочернего процесса также создаются три файла tmp/in, tmp/out и tmp/err, в которые будет записываться все, что проходит через stdin, stdout и stderr simple2 соответственно. Вот утилита Unix, которая копирует все из stdin в stdout, но при необходимости также записывает все это в файлы, указанные в качестве аргументов.

AMG: Вот одна строка для создания пустого файла:

glennj: см. также "touch" из пакета tcllib, fileutil .

Конвейеры команд

Конвейеры команд, выполняемые open, генерируют ошибки точно так же, как описано для exec , и close возвращает ошибку, когда получает канал, возвращенный open в качестве аргумента. Однако нет опции -ignorestderr. Один из способов обойти это — перенаправить stderr, возможно, прямо обратно на stderr: >@stderr .

AMG: я предпочитаю создавать первый аргумент для открытия следующим образом: |[list progname arg1 arg2 arg3 . ]. Это защищает от пробелов, встроенных в аргументы, от путаницы в работе. Даже если с вашей командной строкой проблем нет, однажды вы можете изменить ее, возможно, чтобы использовать параметр вашего процесса в качестве аргумента. Поэтому я просто делаю это «правильно», с самого начала, чтобы не забыть внести изменения в будущем. Это как проблема с необязательными фигурными скобками в C: они не нужны для однострочного if / for / while /etc. тела, но когда вы добавляете другую строку, вы можете забыть добавить фигурные скобки.

Захват stdout, stderr и статуса дочернего выхода

Следующая процедура вызывает внешнюю команду и возвращает вывод, вывод диагностики и код выхода этой команды.

Вот похожая процедура, которая выполняет почти то же самое, что и первая, за исключением того, что в одном случае она оставляет артефакт в выводе stderr. Если дочерний процесс ничего не генерирует для stderr, но имеет статус завершения, отличный от 0 , exec записывает в stderr следующее сообщение: «дочерний процесс завершился ненормально»:

Еще один способ — перенаправить stderr на stdout , чтобы захватить только один поток:

Вот быстрая тестовая последовательность, в которой используется метод close, возвращающий стандартную ошибку для блокирующих каналов:

Вывод должен быть:

Асинхронный захват stdout, stderr и статуса дочернего выхода

Следующий код представляет собой шаблон для выполнения внешней программы и асинхронного сбора stdout, stderr и кода выхода.

Этот пример также доступен в ycl::exec.

Захват stdout и stderr с помощью внешнего «насоса»

В СОВЕТЕ 304 Александр Феррье пишет: Популярный обходной путь для пуристов, использующих только скрипты и желающих получить доступ к stderr команды, заключается в создании внешнего «насоса», такого как cat, в открытом файле . r+ и ​​перенаправить нужный stderr на сторону записи насоса. Затем его вывод можно отслеживать через сторону чтения:

Теперь это, конечно, почти элегантно, сложно развернуть в Windows (где вам нужен дополнительный cat.exe) и не особенно эффективно, поскольку «насос» потребляет контекстные переключатели и пропускную способность памяти только для эмуляции одного канала ОС. когда Tcl вынужден создать два из них через open . р+ .

MSW: обратите внимание, что одновременная передача stderr и stdout не будет работать для всех операционных систем. Помню, у соляриса были проблемы с потерей данных через каналы (один заполнялся, а другой не сливался?). Мне пришлось перенаправить материал в файлы и просмотреть файлы, чтобы следить за выводом (вызванная программа была cvs). Кроме того, различия в буферизации мешают, когда вы пытаетесь одновременно поймать ошибку и уйти. Я не пробовал точное предложенное выше решение. Кто-то с Solaris 8 и 9 может захотеть проверить это (нет доступа к одному банкомату).

Предостережение: режим а

Для режима a Tcl ищет (seek()) конец файла сразу после открытия файла и предполагает, что этого достаточно, но это может вызвать состояние гонки. если другая программа добавит файл раньше, чем эта. Если система выполняет правильное (безопасное для потоков и процессов) добавление, как того требует POSIX, это не проблема. Правильное поведение при добавлении, как правило, поддерживается в системе на ранних этапах, потому что оно полезно для предотвращения потери данных из системных журналов.

Вот как определить проблемную систему:

Откройте файл в режиме добавления (с помощью a или a+ ) несколько раз и каждый раз записывайте в файл одну строку (я предлагаю писать здесь цифры; это легко понять!) Не сбрасывайте и не закрывайте эти файлы явным образом. ручки. Вместо этого выйдите из программы; код закрытия языка должен обрабатывать сброс и закрытие для вас. Затем просмотрите содержимое полученного файла. Проверьте, действительно ли все записанные вами значения попали в файл. Порядок здесь не имеет значения. Если вы написали все строки, это хорошо.

В проблемной системе использование флага APPEND, который транслируется в низкоуровневый флаг O_APPEND для системного вызова PrivoxyWindowOpen(), изменяет семантику записи таким образом, что происходит поиск конца. как атомарная часть самой записи, и это гарантирует, что никакие данные никогда не будут потеряны, хотя, конечно, приложениям все равно нужно позаботиться о том, чтобы когда-либо записывать в файл только полные записи/строки.

Имеет ли текущее поведение Tcl (8.4.1.1 и более ранние версии) некоторое преимущество перед поведением APPEND? Или эту разницу следует считать исправленной ошибкой?

FW секундирует этот вопрос.

LES: 2005-04-11: Последнее обновление этой страницы имело отметку "2003-09-01", когда я пришел сюда и изменил его.Ответ на этот вопрос уже дан?

Ларс Х: Рискну ответить. Возможно, преимущество over APPEND в том, что оно менее удивительно?! Представьте себе программу, которая добавляет некоторые данные, например. список изменений, а затем ищет начало, чтобы записать обновленную временную метку. Если бы кто-то вошел и заменил эту «а» на, то неожиданным результатом было бы то, что все метки времени оказались бы в конце файла, потому что каждый пут будет стремиться к концу, не так ли?

DKF: Если вам нужен произвольный доступ к файлу, вы не должны использовать "a". Вы бы точно не стали этого делать, если бы использовали stdio.

Создайте собственный конвейер

PYK 27 апреля 2015 г.: начиная с версии 8.6 можно закрыть только одну сторону канала. Помимо прочего, это можно использовать для использования другой программы в качестве фильтра данных:

Альтернативные потоки данных Windows

В Windows есть возможность хранить несколько потоков данных в одном файле:

Поскольку в основном потоке нет данных, сообщается, что размер файла равен 0 .

В оболочке MS-DOS указание имени файла, оканчивающегося двоеточием, приводит к использованию основного потока:

В Tcl попытка открыть файл, имя которого заканчивается на :, является ошибкой.

Последовательные порты

Параметры fconfigure, специфичные для определенного типа канала, задокументированы на справочной странице команды, создающей этот тип канала. Поэтому параметр -mode для последовательных портов задокументирован на справочной странице для open .

Примеры: альфа-канал

В Alpha есть множество реальных примеров взаимодействия с внешними процессами с помощью конвейеров. Примеры включают

<УЛ>
  • заклинание
  • tex, bibtex, dvips, gs (на самом деле это очень причудливый Tcl-интерфейс для tex, включающий множество приемов Tcl, таких как регулярные выражения файлов журнала, чтобы понять, что делать дальше, и т. д.)
  • maxima (см. описание на этой вики в Maxima через трубу)
  • coq
  • а также стандартные оболочки. В AlphaTcl Wiki есть несколько страниц, посвященных этим вопросам.

    см., в частности, Alpha и Unix , обзорную страницу. Обсуждаемые проблемы включают в себя, как захватить stderr, как отфильтровать подсказки и преобразовать асинхронное взаимодействие в синхронное с механизмами тайм-аута с помощью vwait, как связать процесс с окном, как предоставить активные ячейки в альфа-документе, сортировку интерфейса рабочего листа для внешнего процесса, как обеспечить пошаговую функциональность (проходя через список команд, на каждом шаге видя результат в консоли) и проверку орфографии при вводе (используя aspell).

    Скрытые файлы Windows

    Попытка открыть скрытый файл в режиме w завершится ошибкой:

    Однако открытие такого файла в режиме r+ будет успешным. Это связано с тем, какие флаги open передаются функции [Microsoft Windows%|%Windows, CreateFile . Один соответствующий отрывок из этой документации:

    Если указаны CREATE_ALWAYS и FILE_ATTRIBUTE_NORMAL, функция CreateFile завершается ошибкой и устанавливает для последней ошибки значение ERROR_ACCESS_DENIED, если файл существует и имеет атрибут FILE_ATTRIBUTE_HIDDEN или FILE_ATTRIBUTE_SYSTEM. Чтобы избежать ошибки, укажите те же атрибуты, что и у существующего файла.

    CreateFile Функция Windows API IOError: [Errno 13 Отказано в доступе при попытке открыть скрытый файл в режиме «w», stackoverflow, 04.11.2012

    Возможный ответ на вопрос: Plink

    marcDouglas: Думаю, проблема была в операторе fconfigure. Я удалил последние две опции ( -translation crlf -eofchar <> ), и теперь это работает для меня. Спасибо за небольшой скрипт, он отлично работает, чтобы начать то, что я хотел сделать.

    Управление файлами с помощью Tcl

    Tcl обеспечивает тонкий уровень абстракции над файловой системой Unix. Я говорю, потому что вы действительно можете увидеть Unix через него, но это достаточно абстракция, чтобы быть переносимой на большинство современных операционных систем. (Возможно, это связано с успехом C, который привел к тому, что большинство современных операционных систем поддерживают плоские файлы в стиле Unix.) Расширенный Tcl добавляет команды для обеспечения прямого доступа к системным вызовам Unix, что делает язык пригодным для системного программирования.< /p>

    Файловые дескрипторы

    В случае успеха команда open возвращает дескриптор файла или , который представляет собой строку. В общем, вы должны обращаться с этой строкой как с черным ящиком: вам никогда не нужно смотреть на нее или печатать ее, просто сохраните ее в переменной, чтобы передать ее в качестве аргумента другим командам.

    Стандартные файловые дескрипторы

    Интерпретатор Tcl делает доступными для вашей программы три стандартных файловых дескриптора Unix. Стандартный ввод доступен как файловый дескриптор stdin ; стандартный вывод доступен как файловый дескриптор stdout , а стандартная ошибка доступна как файловый дескриптор stderr .

    Абстракция файла

    Создание файла

    Удаление файла

    Стандартный Tcl не имеет возможности удалить файл. Однако это легко сделать, вызвав внешнюю стандартную программу rm:

    Расширенный Tcl имеет команду unlink, которая принимает переменное количество аргументов, являющихся именами файлов, и удаляет их.

    Открытие файла

    Команда open принимает два аргумента: путь и (необязательно) тип доступа. Конечно, путь может быть абсолютным или относительным. open поддерживает две записи для метода доступа: обе имитируют различные функции библиотеки C.

    Если второй аргумент не указан, по умолчанию используется значение r .

    Метод доступа в строковом стиле

    Для указания метода доступа используется один строковый аргумент, один из следующих: r Только чтение, без создания r+ Чтение/запись, без создания w Только запись, усечение или создание w+ Чтение/запись, усечение или создание Только запись, добавить или создать+ Чтение/запись, добавление или создание

    Метод доступа в виде списка

    В качестве второго аргумента может быть указан список любых из следующих флагов; ровно один из RDONLY , WRONLY или RDWR должен быть включен в список. RDONLY Файл открыт только для чтения. ОШИБОЧНО Файл открыт только для записи. RDWR Файл открыт для чтения и записи. APPEND Указатель файла устанавливается в EOF перед каждой записью. CREAT Файл создается, если он еще не существует. EXCL Используется с CREAT , генерирует ошибку, если уже существует (монопольный доступ). НЕБЛОКИРОВАТЬ Не блокировать при открытии файла; обычно применяется только к fifos и сокетам. TRUNC Если файл существует, обрезать его до нулевой длины при открытии. NOCTTY Не становитесь управляющим терминалом (это модно и его можно игнорировать.)

    Закрытие файла

    <ПР>
  • У процесса есть только конечное число файловых дескрипторов. В некоторых Unix-системах ограничений может не быть, но в большинстве современных Unix-систем ограничение составляет около 64. Поэтому, если вы обрабатываете огромное количество файлов, даже последовательно, вы должны обязательно закрывать их по ходу работы.< /li>
  • Закрытие файла очищает буферы. Если вы хотите быть уверены, что окончательный буфер, полный данных, будет сброшен на диск, как только вы закончите запись, вы должны закрыть файл. (Но см. Буферизация ниже для более точного контроля.)
  • Команда close просто принимает дескриптор файла в качестве аргумента; сигнализируется ошибка, если файл не может быть закрыт или если он не был открыт.

    Запись в файл

    Команда puts принимает дескриптор файла и строку и записывает эту строку в файл с добавлением завершающей строки (если не задан параметр -nonewline). При вызове только с одним аргументом строка записывается в стандартный вывод. Эти две команды эквивалентны:

    Чтение из файла

    Tcl имеет две команды для чтения из файла: gets ориентирована на строку, а read ориентирована на блок (и подходит для ввода-вывода с произвольным доступом). Расширенный Tcl добавляет некоторые другие команды: bsearch ищет в отсортированном файле с помощью двоичного поиска, а lgets ориентирован на список (читает списки Tcl).

    Команда gets

    Команда gets существует в двух вариантах. Форма с одним аргументом принимает дескриптор файла в качестве параметра и возвращает следующую строку из файла. Конец файла указывается пустой строкой; поскольку это неоднозначно, вы можете использовать команду eof, чтобы проверить, действительно ли произошел конец файла.

    Более полезной является форма с двумя аргументами, в которой в качестве параметра указывается имя переменной. В этой форме следующая прочитанная строка сохраняется в именованной переменной, и возвращается длина строки, или -1, или конец файла.

    В любом случае завершающий символ новой строки удаляется.

    Вот типичное использование get in the loop для чтения всего файла построчно:

    Команда чтения

    Команда чтения принимает два параметра: файловый дескриптор и счетчик. Второй параметр является необязательным. Если указано, read читает следующее количество байтов из файла (или до конца файла, если осталось меньше, чем число байтов). Байты возвращаются в виде строки. Если аргумент count не указан, считываются и возвращаются все остальные байты в файле.

    Команда bsearch

    Команда bsearch выполняет двоичный поиск в открытом файле. В своей простейшей форме он принимает дескриптор файла и строку для поиска и возвращает совпадающую строку, если она найдена, или пустую строку. Он также принимает необязательное имя переменной, например, gets, и в этом случае возвращает логическое значение. (Подробнее см. в TclX(7tcl).)

    Команда lgets

    Команда lgets считывает списки Tcl. Он принимает те же аргументы, что и gets , и возвращает результаты таким же образом, но читает списки Tcl, а не строки.

    Этой командой легко запутаться. В частности, точно так же, как ошибочно рассматривать произвольную строку как список, так же ошибочно использовать lgets в файле, который не был записан с помощью Tcl.

    Для записи списков в файл в форме, которую оценит lgets, требуется только, чтобы правильные списки были записаны в файл с помощью puts . В этом примере обратите внимание на новую строку во втором списке, которая иллюстрирует разницу между lgets и gets :

    Команда eof

    Состояние конца файла любого дескриптора файла можно проверить в любое время с помощью команды eof, которая принимает дескриптор файла в качестве аргумента и возвращает значение true (1), если достигнут конец файла, или false (0). ) иначе. Вот альтернативный способ чтения всех строк из файла с помощью eof:

    Произвольный доступ

    Перемещение указателя файла: поиск в файле

    <УЛ>
  • start (начало файла)
  • current (указатель текущего файла)
  • конец (конец файла)
  • seek всегда возвращает пустую строку, поэтому единственный способ узнать, удался ли поиск, — это использовать команду tell и проверить, попали ли вы туда, куда направлялись. Это ошибка дизайна Tcl, особенно с учетом того, что системный вызов поиска Unix возвращает статус.

    Вот код, который считывает файл с изображениями карточек из 80 столбцов:

    Запрос указателя файла

    Команда tell возвращает текущую позицию указателя файла для файлового дескриптора fd в виде целого числа.

    Буферизация

    По умолчанию файлы, открытые для записи с помощью Tcl, буферизуются блоками. На самом деле вы можете управлять буферизацией с помощью расширенных команд Tcl, но самый простой подход — использовать команду очистки после записи. Сброс обычно не нужен при работе с файлами (и на самом деле замедляет работу), но очень важен при работе с IPC.

    Текущий рабочий каталог

    Команда cd изменяет текущий рабочий каталог (CWD) процесса Tcl на имя_каталога (или на домашний каталог пользователя, если имя_каталога не указано). Команда pwd возвращает CWD в виде строки.

    Чтение каталогов

    Команда glob обеспечивает легкий доступ к содержимому каталогов. Он берет те же шаблоны глобусов, которые мы видели раньше (например, в команде switch), и применяет их к именам файлов, хранящимся в каталоге, возвращая список совпадающих имен файлов. Если нет подходящих имен файлов, выдается сообщение об ошибке (если не указано -nocomplain). Если шаблоны указаны как абсолютные пути, возвращаемые имена файлов также будут абсолютными.

    Команда файла

    Команда file объединяет несколько разных команд для работы с файлами в одном месте. Существуют команды для управления именами файлов, проверки существования файла и запроса индексного дескриптора.

    Управление именами файлов

    Хотя в Unix не используются обязательные расширения имен файлов, как в MS/DOS, расширения используются традиционно, поэтому Tcl предоставляет команды для простой работы с ними. Картинка стоит тысячи слов:

    Файловые предикаты

    Команда file предоставляет несколько предикатов для проверки файлов. Все возвращают логическое значение (1 или 0). доступный для чтения , доступный для записи и принадлежащий файлу тест относительно пользователя, выполняющего скрипт Tcl.

    Доступ к Inode

    Команда file stat считывает индексный дескриптор имени и заполняет переменную массива arrayname записями для каждого поля в индексном дескрипторе.

    Поля индексного дескриптора названы следующим образом: nlink Количество ссылок. uid UID владельца файла. gid GID группы файла. режим Режим файла в виде десятичного (!) целого числа. Сюда входят пользовательские, групповые и другие разрешения, а также несколько других битов (биты setuid и setgid и бит sticky). size Размер в байтах. atime Время последнего доступа в виде десятичного целого числа (секунды с эпохи Unix). mtime Время последней модификации, как указано выше. ctime Время последнего изменения индекса, как указано выше. ino I-число. dev Устройство, на котором находится файл; вместе с I-номером эти два значения однозначно идентифицируют файл.

    Команда типа файла возвращает строку, представляющую тип файла, один из следующих: file , directory , characterSpecial , blockSpecial , fifo , link или socket .

    Доступ к Inode через файловый дескриптор

    Расширенный Tcl предоставляет доступ к содержимому индексных дескрипторов с помощью команды fstat. Эта команда дублирует команду file stat, за исключением того, что если file stat работает с именованным файлом, то fstat работает с файловым дескриптором.

    fstat существует в трех вариантах, каждый из которых имеет обязательный аргумент файлового дескриптора. В первой форме без дополнительных аргументов все поля индексного дескриптора возвращаются в виде списка с ключами. Во второй форме возвращается только определенное значение для именованного поля в виде строки. В третьей форме все поля вводятся в именованную переменную массива.

    Читайте также: