<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <title>fcopy</title>
  </head>

  <body>
    <h1>fcopy</h1>

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

    <pre>
      <strong>fcopy</strong> <em>inchan</em> <em>outchan</em> ?<em>-size</em> <em>size</em>? ?<em>-command</em> <em>callback</em>?
    </pre>

    <h2>ОПИСАНИЕ</h2>

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

    <p>Команда <strong>fcopy</strong> передает данные из канала <em>inchan</em>,
      пока не будет достигнут конец файла или не будет передано
      <em>size</em> байтов. Если аргумент <em>-size</em> не задан,
      передается весь файл. Если опция <em>-command</em> не задана,
      команда блокирует процесс до завершения копирования и возвращает
      число переданных байтов.</p>
    
    <p>При наличии аргумента <em>-command</em> команда <strong>fcopy</strong>
      работает в фоновом режиме. Она завершается немедленно, а команда
      <em>callback</em> вызывается позже, когда завершается процесс
      копирования. Команда <em>callback</em> вызывается с одним или
      двумя дополнительными аргументами, которые указывают число
      переданных байтов. Если при исполнении фонового процесса
      произошла ошибка, второй аргумент - строка описания ошибки. При
      фоновом выполнении копирования каналы <em>inchan</em> и
      <em>outchan</em> не обязательно открывать в неблокирующем режиме,
      команда <strong>fcopy</strong> выполнит это автоматически. Однако при
      этом необходимо организовать обработку событий, например, с
      помощью команды <a href="vwait.html"><strong>vwait</strong></a> или
      используя Tk.</p>

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

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

    <p>Команда <strong>fcopy</strong> преобразует символы конца строк в
      соответствии со значениями опций <em>-translation</em> для
      соответствующих каналов (см. описание команды <a
      href="fconfigure.html"><strong>fconfigure</strong></a>). Преобразование
      означает, в частности, что число прочитанных и число переданных
      символов может отличаться. В синхронном режиме команда
      возвращает только число переданных в <em>outchan</em> канал
      символов. В фоновом режиме только это число подается на вход
      команды callback.</p>

    <h2>ПРИМЕРЫ</h2> 

    <p> Первый пример показывает, как в фоновом режиме получить число
      переданных байтов. Конечно, это показательный пример, поскольку
      то же самое может быть сделано проще без использования фонового
      режима.</p>
    <pre>
      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
    </pre>

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

    <pre>
      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
    </pre>

    <p>См. также <a href="eof.html"><strong>eof</strong></a>(n), <a href=
      "fblocked.html"><strong>fblocked</strong></a>(n), <a href=
      "fcopy.html"><strong>fconfigure</strong></a>(n).</p>

  </body>
</html>