fcopy

Копирует данные из одного канала в другой.

      fcopy inchan outchan ?-size size? ?-command callback?
    

ОПИСАНИЕ

Команда fcopy копирует данные из одного канала ввода - вывода, заданного идентификатором канала inchan, в другой канал ввода - вывода, заданный идентификатором канала outchan. Команда позволяет упростить буферизацию и избежать излишнего копирования в Tcl-системе ввода - вывода, а также избежать использования больших объемов памяти при копировании данных по таким медленным каналам, как сетевые соединения.

Команда fcopy передает данные из канала inchan, пока не будет достигнут конец файла или не будет передано size байтов. Если аргумент -size не задан, передается весь файл. Если опция -command не задана, команда блокирует процесс до завершения копирования и возвращает число переданных байтов.

При наличии аргумента -command команда fcopy работает в фоновом режиме. Она завершается немедленно, а команда callback вызывается позже, когда завершается процесс копирования. Команда callback вызывается с одним или двумя дополнительными аргументами, которые указывают число переданных байтов. Если при исполнении фонового процесса произошла ошибка, второй аргумент - строка описания ошибки. При фоновом выполнении копирования каналы inchan и outchan не обязательно открывать в неблокирующем режиме, команда fcopy выполнит это автоматически. Однако при этом необходимо организовать обработку событий, например, с помощью команды vwait или используя Tk.

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

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

Команда fcopy преобразует символы конца строк в соответствии со значениями опций -translation для соответствующих каналов (см. описание команды fconfigure). Преобразование означает, в частности, что число прочитанных и число переданных символов может отличаться. В синхронном режиме команда возвращает только число переданных в outchan канал символов. В фоновом режиме только это число подается на вход команды callback.

ПРИМЕРЫ

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

      proc Cleanup {in out bytes {error {}}} {
          global total
          set total $bytes
          close $in
          сlose $out
          if {[string length $error]!= 0} { 
              # error occurred during the copy
          }
      }
      #### Открыть файл на чтение
      set in [open $file1]
      #### Открыть сетевое соединение
      set out [socket $server $port]
      #### Скопировать, по окончании копирования вызвать
      Cleanup
      fcopy $in $out -command [list Cleanup $in $out]
      #### Ожидать завершения копирования
      vwait total
    

Второй пример показывает, как можно организовать копирование файла по фрагментам и проверять конец файла.

      proc CopyMore {in out chunk bytes {error {}}} { 
          global total done
          incr total $bytes
          if {([string length $error]!= 0) || [eof $in] {
              set done $total
              close $in
              close $out
          } else {
              fcopy $in $out -command [list CopyMore $in $out $chunk] \
                  -size $chunk
          }
      }
      set in [open $file1]
      set out [socket $server $port]
      #### Установить размер фрагмента для копирования.
      set chunk 1024
      set total 0
      fcopy $in $out -command [list CopyMore $in $out $chunk]\
          -size $chunk
      vwait done
    

См. также eof(n), fblocked(n), fconfigure(n).