Scroll to navigation

chan(3tcl) Tcl Built-In Commands chan(3tcl)


NAME

chan - Reads, writes and manipulates channels.

SYNOPSIS

chan operation ?arg arg ...?


DESCRIPTION

chan provides several operations for reading from, writing to, and otherwise manipulating channels, e.g. those created by open and socket, or the default channels stdin, stdout or stderr which correspond respectively to the standard input, output, and error streams of the process. Any unique abbreviation for operation is acceptable. Available operations are:

Returns 1 when the channel is in non-blocking mode and the last input operation on the channel failed because it would have otherwise caused the process to block, and 0 otherwise. Each Tcl channel is in blocking mode unless configured otherwise.
Closes and destroys the named channel deleting any existing event handlers established for the channel. The command returns the empty string. If direction is given, it is read, or write, or any unique abbreviation of those words, and only that side of the channel is closed. I.e. a read-write channel may become read-only or write-only. Closing a read-only channel for reading, or closing a write-only channel for writing is the same as simply closing the channel. It is an error to close a read-only channel for writing or to close a write-only channel for reading.

When a channel is closed for writing, any buffered output on the channel is flushed. When a channel is closed for reading, any buffered input is discarded. When a channel is destroyed the underlying resource is closed and the channel is thereafter unavailable.

chan close fully flushes any output before closing the write side of a channel unless it is non-blocking mode, where it returns immediately and the channel is flushed in the background before finally being closed.

chan close may return an error if an error occurs while flushing output. If a process in a command pipeline created by open returns an error (either by returning a non-zero exit code or writing to its standard error file descriptor), chan close generates an error in the same manner as exec.

Closing one side of a socket or command pipeline may lead to the shutdown() or close() of the underlying system resource, leading to a reaction from whatever is on the other side of the pipeline or socket.

If the channel for a command pipeline is in blocking mode, chan close waits for the connected processes to complete.

chan close only affects the current interpreter. If the channel is open in any other interpreter, its state is unchanged there. See interp for a description of channel sharing.

When the last interpreter sharing a channel is destroyed, the channel is switched to blocking mode and fully flushed and then closed.

Channels are automatically closed when an interpreter is destroyed and when the process exits. From 8.6 on (TIP#398), nonblocking channels are no longer switched to blocking mode when exiting; this guarantees a timely exit even when the peer or a communication channel is stalled. To ensure proper flushing of stalled nonblocking channels on exit, one must now either (a) actively switch them back to blocking or (b) use the environment variable TCL_FLUSH_NONBLOCKING_ON_EXIT, which when set and not equal to “0” restores the previous behavior.

Configures or retrieves the configuration of the channel channelName.

If no optionName or value arguments are given, chan configure returns a dictionary of option names and values for the channel. If optionName is supplied without a value, chan configure returns the current value of the named option. If one or more pairs of optionName and value are supplied, chan configure sets each of the named options to the corresponding value and returns the empty string.

The options described below are supported for all channels. Each type of channel may provide additional options. Those options are described in the relevant documentation. For example, additional options are documented for socket, and also for serial devices at open.

If -blocking is set to true (default), reading the channel or writing to it may cause the process to block indefinitely. Otherwise, operations such as chan gets, chan read, chan puts, chan flush, and chan close take care not to block. Non-blocking mode in general requires that the event loop is entered, e.g. by calling Tcl_DoOneEvent or vwait or by using Tk, to give Tcl a chance to process events on the channel.
If newValue is full, which is the default, output is buffered until the internal buffer is full or until chan flush is called. If newValue is line, output is flushed each time a end-of-line character is written. If newValue is none, output is flushed after every output operation. For stdin, stdout, and channels that connect to terminal-like devices, the default value is line. For stderr the default value is none.
newSize, an integer no greater than one million, is the size in bytes of any input or output buffers subsequently allocated for this channel.
Sets the encoding of the channel to name which should be one of the names returned by encoding names, or “binary” . Input is converted from the encoding into Unicode, and output is converted from Unicode to the encoding.

binary is an alias for iso8859-1. This alone is not sufficient for working with binary data. Use -translation binary instead.

The encoding of a new channel is the value of encoding system, which returns the platform- and locale-dependent system encoding used to interface with the operating system,

char signals the end of the data when it is encountered in the input. If char is the empty string, there is no special character that marks the end of the data.

The default value is the empty string. The acceptable range is \x01 - \x7F. A value outside this range results in an error.

Specifies the encoding profile to be used on the channel. The encoding transforms in use for the channel's input and output will then be subject to the rules of that profile. Any failures will result in a channel error. See PROFILES in the encoding(3tcl) documentation for details about encoding profiles.
In Tcl a single line feed (\n) represents the end of a line. However, at the destination the end of a line may be represented differently on different platforms, or even for different devices on the same platform. For example, under UNIX line feed is used in files and a carriage-return-linefeed sequence is normally used in network connections. Therefore, on input, e.g. with chan gets and chan read, each external end-of-line character is translated into a line feed. On output, e.g. with chan puts, each line feed is translated to the external end-of-line character. The default translation, auto, handles all the common cases, and -translation provides explicit control over the end-of-line character.

Returns the input translation for a read-only channel, the output translation for a write-only channel, and both the input translation and the output translation for a read-write channel. When two translations are given, they are the input and output translation, respectively. When only one translation is given for a read-write channel, it is the translation for both input and output. The following values are currently supported:

The default. For input each occurrence of a line feed (lf), carriage return (cr), or carriage return followed by a line feed (crlf) is translated into a line feed. For output, each line feed is translated into a platform-specific representation: For all Unix variants it is lf, and for all Windows variants it is crlf, except that for sockets on all platforms it is crlf for both input and output.
Like lf, no end-of-line translation is performed, but in addition, sets -eofchar to the empty string to disable it, and sets -encoding to iso8859-1. With this one setting, a channel is fully configured for binary input and output: Each byte read from the channel becomes the Unicode character having the same value as that byte, and each character written to the channel becomes a single byte in the output. This makes it possible to work seamlessly with binary data as long as each character in the data remains in the range of 0 to 255 so that there is no distinction between binary data and text. For example, A JPEG image can be read from a such a channel, manipulated, and then written back to such a channel.
The end of a line is represented in the external data by a single carriage return character. For input, each carriage return is translated to a line feed, and for output each line feed character is translated to a carriage return.
The end of a line is represented in the external data by a carriage return character followed by a line feed. For input, each carriage-return-linefeed sequence is translated to a line feed. For output, each line feed is translated to a carriage-return-linefeed sequence. This translation is typically used for network connections, and also on Windows systems.
The end of a line in the external data is represented by a line feed so no translations occur during either input or output. This translation is typically used on UNIX platforms,
Reads characters from inputChan and writes them to outputChan until all characters are copied, blocking until the copy is complete and returning the number of characters copied. Leverages internal buffers to avoid extra copies and to avoid buffering too much data in main memory when copying large files to slow destinations like network sockets.

-size limits the number of characters copied.

If -command is given, chan copy returns immediately, works in the background, and calls callback when the copy completes, providing as an additional argument the number of characters written to outputChan. If an error occurs during the background copy, another argument provides message for the error. inputChan and outputChan are automatically configured for non-blocking mode if needed. Background copying only works correctly if events are being processed, e.g. via vwait or Tk.

During a background copy no other read operation may be performed on inputChan, and no write operation may be performed on outputChan. However, write operations may by performed on inputChan and read operations may be performed on outputChan, as exhibited by the bidirectional copy example below.

If either inputChan or outputChan is closed while the copy is in progress, copying ceases and no callback is made. If inputChan is closed all data already queued is written to outputChan.

There should be no event handler established for inputChan because it may become readable during a background copy. An attempt to read or write from within an event handler results result in the error, "channel busy". Any wrong-sided I/O attempted (by a chan event handler or otherwise) results in a “channel busy” error.

Creates a new channel, called a reflected channel, with cmdPrefix as its handler, and returns the name of the channel. cmdPrefix is the first words of a command that provides the interface for a refchan.

Imode is a list of one or more of the strings “read” or “write”, indicating whether the channel is a read channel, a write channel, or both. It is an error if the handler does not support the chosen mode.

The handler is called as needed from the global namespace at the top level, and command resolution happens there at the time of the call. If the handler is renamed or deleted any subsequent attempt to call it is an error, which may not be able to describe the failure.

The handler is always called in the interpreter and thread it was created in, even if the channel was shared with or moved into a different interpreter in a different thread. This is achieved through event dispatch, so if the event loop is not entered, e.g. by calling Tcl_DoOneEvent or vwait or using Tk, the thread performing the channel operation blocks indefinitely, resulting in deadlock.

One side of a channel may be in one thread while the other side is in a different thread, providing a stream-oriented bridge between the threads. This provides a method for regular stream communication between threads as an alternative to sending commands.

When the interpreter the handler is in is deleted each channel associated with the handler is deleted as well, regardless of which interpreter or thread it is currently in or shared with.

chan create is safe and is accessible to safe interpreters. The handler is always called in the safe interpreter it was created in.

Returns 1 if the last read on the channel failed because the end of the data was already reached, and 0 otherwise.
Arranges for the given script, called a channel event handler, to be called whenever the given event, one of “readable” or “writable” occurs on the given channel, replacing any script that was previously set. If script is the empty string the current handler is deleted. It is also deleted when the channel is closed. If script is omitted, either the existing script or the empty string is returned. The event loop must be entered, e.g. via vwait or update, or by using Tk, for handlers to be evaluated.

script is evaluated at the global level in the interpreter it was established in. Any resulting error is handled in the background, i.e. via interp bgerror. In order to prevent an endless loop due to a buggy handler, the handler is deleted if script returns an error so that it is not evaluated again.

Without an event handler, chan gets or chan read on a channel in blocking mode may block until data becomes available, during which the thread is unable to perform other work or respond to events on other channels. This could cause the application to appear to “freeze up” . Channel event handlers allow events on the channel to direct channel handling so that the reader or writer can continue to perform other processing while waiting for a channel to become available and then handle channel operations when the channel is ready for the operation.

A channel is considered to be readable if there is unread data available on the underlying device. A channel is also considered to be readable if there is unread data in an input buffer, except in the special case where the most recent attempt to read from the channel was a chan gets call that could not find a complete line in the input buffer. This feature allows a file to be read a line at a time in non-blocking mode using events. A channel is also considered to be readable if an end of file or error condition is present on the underlying file or device. It is important for script to check for these conditions and handle them appropriately; for example, if there is no special check for end of file, an infinite loop may occur where script reads no data, returns, and is immediately invoked again.

A channel is considered to be writable if at least one byte of data can be written to the underlying file or device without blocking, or if an error condition is present. Note that client sockets opened in asynchronous mode become writable when they become connected or if the connection fails.

Event-driven channel handling works best for channels in non-blocking mode. A channel in blocking mode blocks when chan puts writes more data than the channel can accept at the moment, and when chan gets or chan read requests more data than is currently available. When a channel blocks, the thread can not do any other processing or service any other events. A channel in non-blocking mode allows a thread to carry on with other work and get back to the channel at the right time.

For a channel in blocking mode, flushes all buffered output to the destination, and then returns. For a channel in non-blocking mode, returns immediately while all buffered output is flushed in the background as soon as possible.
Reads a line from the channel consisting of all characters up to the next end-of-line sequence or until end of file is seen. The line feed character corresponding to end-of-line sequence is not included as part of the line. If the varName argument is specified, the line is stored in the variable of that name and the command returns the length of the line. If varName is not specified, the command returns the line itself as the result of the command.

If a complete line is not available and the channel is not at EOF, the command will block in the case of a blocking channel. For non-blocking channels, the command will return the empty string as the result in the case of varName not specified and -1 if it is.

If a blocking channel is already at EOF, the command returns an empty string if varName is not specified. Note an empty string result can also be returned when a blank line (no characters before the next end of line sequence). The two cases can be distinguished by calling the chan eof command to check for end of file. If varName is specified, the command returns -1 on end of file. There is no ambiguity in this case because blank lines result in 0 being returned.

If a non-blocking channel is already at EOF, the command returns an empty line if varName is not specified. This can be distinguished from an empty line being returned by either a blank line being read or a full line not being available through the use of the chan eof and chan blocked commands. If chan eof returns true, the channel is at EOF. If chan blocked returns true, a full line was not available. If both commands return false, an empty line was read. If varName was specified for a non-bocking channel at EOF, the command returns -1. This can be distinguished from full line not being available either by chan eof or chan blocked as above. Note that when varName is specified, there is no need to distinguish between eof and blank lines as the latter will result in the command returning 0.

If the encoding profile strict is in effect for the channel, the command will raise an exception with the POSIX error code EILSEQ if any encoding errors are encountered in the channel input data. The file pointer remains unchanged and it is possible to introspect, and in some cases recover, by changing the encoding in use. See ENCODING ERROR EXAMPLES later.

Returns a list of all channel names, or if pattern is given, only those names that match according to the rules of string match.
Returns the number of bytes of input when mode is “input” , or output when mode is “output” , that are currently internally buffered for the channel. Useful in a readable event callback to impose limits on input line length to avoid a potential denial-of-service attack where an extremely long line exceeds the available memory to buffer it. Returns -1 if the channel was not opened for the mode in question.
Creates a pipe, i.e. a readable channel and a writable channel, and returns the names of the readable channel and the writable channel. Data written to the writable channel can be read from the readable channel. Because the pipe is a real system-level pipe, it can be connected to other processes using redirection. For example, to redirect stderr from a subprocess into one channel, and stdout into another, exec with "2>@" and ">@", each onto the writable side of a pipe, closing the writable side immediately thereafter so that EOF is signaled on the read side once the subprocess has closed its output, typically on exit.

Due to buffering, data written to one side of a pipe might not immediately become available on the other side. Tcl's own buffers can be configured via chan configure -buffering, but overall behaviour still depends on operating system buffers outside of Tcl's control. Once the write side of the channel is closed, any data remaining in the buffers is flushed through to the read side. It may be useful to arrange for the connected process to flush at some point after writing to the channel or to have it use some system-provided mechanism to configure buffering. When two pipes are connected to the same process, one to send data to the process, and one to read data from the process, a deadlock may occur if the channels are in blocking mode: If reading, the channel may block waiting for data that can never come because buffers are only flushed on subsequent writes, and if writing, the channel may block while waiting for the buffers to become free, which can never happen because the reader can not read while the writer is blocking. To avoid this issue, either put the channels into non-blocking mode and use event handlers, or place the read channel and the write channel in separate interpreters in separate threads.

Removes the topmost transformation handler from the channel if there is one, and closes the channel otherwise. The result is normally the empty string, but may be an error in some situations, e.g. when closing the underlying resource results in an error.
For use by handlers established with chan create. Notifies Tcl that that one or more event(s) listed in eventSpec, each of which is either “read” or “write.” , have occurred.

For use only by handlers for a channel created by chan create. It is an error to post an event for any other channel.

Since only the handler for a reflected channel channel should post events it is an error to post an event from any interpreter other than the interpreter that created the channel.

It is an error to post an event that the channel has no interest in. See watch in the refchan documentation for more information

chan postevent is available in safe interpreters, as any handler for a reflected channel would have been created, and will be evaluated in that interpreter as well.

Adds a new transformation handler on top of the channel and returns a handle for the transformation. cmdPrefix is the first words of a command that provides the interface documented for transchan, and transforms data on the channel, It is an error if handler does not support the mode(s) the channel is in.
Writes string and a line feed to the channel. If -nonewline is given, the trailing line feed is not written. The default channel is stdout.

Each line feed in the output is translated to the appropriate end of line sequence as per the -translation configuration setting of the channel.

Because Tcl internally buffers output, characters written to a channel may not immediately be available at the destination. Tcl normally delays output until the buffer is full or the channel is closed. chan flush forces output in the direction of the destination.

When the output for a channel in blocking mode fills up, chan puts blocks until space in the buffer is available again. On the other hand for a channel in non-blocking mode, it returns immediately and the data is written in the background as fast possible, constrained by the speed at which as the destination accepts it. Output to a channel in non-blocking mode only works properly when the application enters the event loop. When a channel is in non-blocking mode, Tcl's internal buffers can hold an arbitrary amount of data, possibly consuming a large amount of memory. To avoid wasting memory, channels in non-blocking mode should normally be handled using chan event, where the application only invokes chan puts after being notified through a file event handler that the channel is ready for more output data.

The command will raise an error exception with POSIX error code EILSEQ if the encoding profile strict is in effect for the channel and the output data cannot be encoded in the encoding configured for the channel. Data may be partially written to the channel in this case.

Reads and returns the next numChars characters from the channel. If numChars is omitted, all available characters up to the end of the file are read, or if the channel is in non-blocking mode, all currently-available characters are read. If there is an error on the channel, reading ceases and an error is returned. If numChars is not given, -nonewline may be given, causing any trailing line feed to be trimmed.

If the channel is in non-blocking mode, fewer characters than requested may be returned. If the channel is configured to use a multi-byte encoding, bytes that do not form a complete character are retained in the buffers until enough bytes to complete the character accumulate, or the end of the data is reached. -nonewline is ignored if characters are returned before reaching the end of the file.

Each end-of-line sequence according to the value of -translation is translated into a line feed.

When reading from a serial port, most applications should configure the serial port channel to be in non-blocking mode, but not necessarily use an event handler since most serial ports are comparatively slow. It is entirely possible to get a readable event for each individual character. In blocking mode, chan read blocks forever when reading to the end of the data if there is no chan configure -eofchar configured for the channel.

If the encoding profile strict is in effect for the channel, the command will raise an exception with the POSIX error code EILSEQ if any encoding errors are encountered in the channel input data. If the channel is in blocking mode, the error is thrown after advancing the file pointer to the beginning of the invalid data. The successfully decoded leading portion of the data prior to the error location is returned as the value of the -data key of the error option dictionary. If the channel is in non-blocking mode, the successfully decoded portion of data is returned by the command without an error exception being raised. A subsequent read will start at the invalid data and immediately raise a EILSEQ POSIX error exception. Unlike the blocking channel case, the -data key is not present in the error option dictionary. In the case of exception thrown due to encoding errors, it is possible to introspect, and in some cases recover, by changing the encoding in use. See ENCODING ERROR EXAMPLES later.

Sets the current position for the data in the channel to integer offset bytes relative to origin. A negative offset moves the current position backwards from the origin. origin is one of the following:
The origin is the start of the data. This is the default.
The origin is the current position.
The origin is the end of the data.

Chan seek flushes all buffered output even if the channel is in non-blocking mode, discards any buffered and unread input, and returns the empty string or an error if the channel does not support seeking.

offset values are byte offsets, not character offsets. Unlike chan read, both chan seek and chan tell operate in terms of bytes, not characters,

Returns the offset in bytes of the current position in the underlying data, or -1 if the channel does not support seeking. The value can be passed to chan seek to set current position to that offset.
Flushes the channel and truncates the data in the channel to length bytes, or to the current position in bytes if length is omitted.

EXAMPLES

SIMPLE CHANNEL OPERATION EXAMPLES

Instruct Tcl to always send output to stdout immediately, whether or not it is to a terminal:

fconfigure stdout -buffering none

In the following example a file is opened using the encoding CP1252, which is common on Windows, searches for a string, rewrites that part, and truncates the file two lines later.

set f [open somefile.txt r+]
chan configure $f -encoding cp1252
set offset 0
# Search for string "FOOBAR" in the file
while {[chan gets $f line] >= 0} {

set idx [string first FOOBAR $line]
if {$idx >= 0} {
# Found it; rewrite line
chan seek $f [expr {$offset + $idx}]
chan puts -nonewline $f BARFOO
# Skip to end of following line, and truncate
chan gets $f
chan gets $f
chan truncate $f
# Stop searching the file now
break
}
# Save offset of start of next line for later
set offset [chan tell $f] } chan close $f

This example illustrates flushing of a channel. The user is prompted for some information. Because the standard input channel is line buffered, it must be flushed for the user to see the prompt.

chan puts -nonewline "Please type your name: "
chan flush stdout
chan gets stdin name
chan puts "Hello there, $name!"

This example reads a file one line at a time and prints it out with the current line number attached to the start of each line.

set chan [open "some.file.txt"]
set lineNumber 0
while {[chan gets $chan line] >= 0} {

chan puts "[incr lineNumber]: $line" } chan close $chan

In this example illustrating event driven reads, GetData will be called with the channel as an argument whenever $chan becomes readable. The read call will read whatever binary data is currently available without blocking. Here the channel has the fileevent removed when an end of file occurs to avoid being continually called (see above). Alternatively the channel may be closed on this condition.

proc GetData {chan} {

set data [chan read $chan]
chan puts "[string length $data] $data"
if {[chan eof $chan]} {
chan event $chan readable {}
} } chan configure $chan -blocking 0 -encoding binary chan event $chan readable [list GetData $chan]

The next example is similar but uses chan gets to read line-oriented data.

proc GetData {chan} {

if {[chan gets $chan line] >= 0} {
chan puts $line
}
if {[chan eof $chan]} {
chan close $chan
} } chan configure $chan -blocking 0 -buffering line -translation crlf chan event $chan readable [list GetData $chan]

A network server that echoes its input line-by-line without preventing servicing of other connections at the same time:

# This is a very simple logger...
proc log message {

chan puts stdout $message } # This is called whenever a new client connects to the server proc connect {chan host port} {
set clientName [format <%s:%d> $host $port]
log "connection from $clientName"
chan configure $chan -blocking 0 -buffering line
chan event $chan readable [list echoLine $chan $clientName] } # This is called whenever either at least one byte of input # data is available, or the channel was closed by the client. proc echoLine {chan clientName} {
chan gets $chan line
if {[chan eof $chan]} {
log "finishing connection from $clientName"
chan close $chan
} elseif {![chan blocked $chan]} {
# Didn't block waiting for end-of-line
log "$clientName - $line"
chan puts $chan $line
} } # Create the server socket and enter the event-loop to wait # for incoming connections... socket -server connect 12345 vwait forever

The following example reads a PPM-format image from a file combining ASCII and binary content.

# Open the file and put it into Unix ASCII mode
set f [open teapot.ppm]
chan configure $f -encoding ascii -translation lf
# Get the header
if {[chan gets $f] ne "P6"} {

error "not a raw-bits PPM" } # Read lines until we have got non-comment lines # that supply us with three decimal values. set words {} while {[llength $words] < 3} {
chan gets $f line
if {[string match "#*" $line]} continue
lappend words {*}[join [scan $line %d%d%d]] } # Those words supply the size of the image and its # overall depth per channel. Assign to variables. lassign $words xSize ySize depth # Now switch to binary mode to pull in the data, # one byte per channel (red,green,blue) per pixel. chan configure $f -translation binary set numDataBytes [expr {3 * $xSize * $ySize}] set data [chan read $f $numDataBytes] close $f

FILE SEEK EXAMPLES

Read a file twice:

set f [open file.txt]
set data1 [chan read $f]
chan seek $f 0
set data2 [chan read $f]
chan close $f
# $data1 eq $data2 if the file wasn't updated

Read the last 10 bytes from a file:

set f [open file.data]
# This is guaranteed to work with binary data but
# may fail with other encodings...
chan configure $f -translation binary
chan seek $f -10 end
set data [chan read $f 10]
chan close $f

Read a line from a file channel only if it starts with foobar:

# Save the offset in case we need to undo the read...
set offset [tell $chan]
if {[read $chan 6] eq "foobar"} {

gets $chan line } else {
set line {}
# Undo the read...
seek $chan $offset }

ENCODING ERROR EXAMPLES

The example below illustrates handling of an encoding error encountered during channel input. First, creation of a test file containing the invalid UTF-8 sequence (A \xC3 B):

% set f [open test_A_195_B.txt wb]; chan puts -nonewline $f A\xC3B; chan close $f

An attempt to read the file will result in an encoding error which is then introspected by switching the channel to binary mode. Note in the example that when the error is reported the file position remains unchanged so that the chan gets during recovery returns the full line.

% set f [open test_A_195_B.txt r]
file384b6a8
% chan configure $f -encoding utf-8 -profile strict
% catch {chan gets $f} e d
1
% set d
-code 1 -level 0
-errorstack {INNER {invokeStk1 gets file384b6a8}}
-errorcode {POSIX EILSEQ {invalid or incomplete multibyte or wide character}}
-errorinfo {...} -errorline 1
% chan tell $f
0
% chan configure $f -encoding binary -profile strict
% chan gets $f
AÃB

The following example is similar to the above but demonstrates recovery after a blocking read. The successfully decoded data "A" is returned in the error options dictionary key -data. The file position is advanced on the encoding error position 1. The data at the error position is thus recovered by the next chan read command.

% set f [open test_A_195_B.txt r]
file35a65a0
% chan configure $f -encoding utf-8 -profile strict -blocking 1
% catch {chan read $f} e d
1
% set d
-data A -code 1 -level 0
-errorstack {INNER {invokeStk1 read file35a65a0}}
-errorcode {POSIX EILSEQ {invalid or incomplete multibyte or wide character}}
-errorinfo {...} -errorline 1
% chan tell $f
1
% chan configure $f -encoding binary -profile strict
% chan read $f
ÃB
% chan close $f

Finally the same example, but this time with a non-blocking channel.

% set f [open test_A_195_B.txt r]
file35a65a0
% chan configure $f -encoding utf-8 -profile strict -blocking 0
% chan read $f
A
% chan tell $f
1
% catch {chan read $f} e d
1
% set d
-code 1 -level 0
-errorstack {INNER {invokeStk1 read file384b228}}
-errorcode {POSIX EILSEQ {invalid or incomplete multibyte or wide character}}
-errorinfo {...} -errorline 1

CHANNEL COPY EXAMPLES

The first example transfers the contents of one channel exactly to another. Note that when copying one file to another, it is better to use file copy which also copies file metadata (e.g. the file access permissions) where possible.

chan configure $in -translation binary
chan configure $out -translation binary
chan copy $in $out

This second example shows how the callback gets passed the number of bytes transferred. It also uses vwait to put the application into the event loop. Of course, this simplified example could be done without the command callback.

proc Cleanup {in out bytes {error {}}} {

global total
set total $bytes
chan close $in
chan close $out
if {$error ne ""} {
# error occurred during the copy
} } set in [open $file1] set out [socket $server $port] chan copy $in $out -command [list Cleanup $in $out] vwait total

The third example copies in chunks and tests for end of file in the command callback.

proc CopyMore {in out chunk bytes {error {}}} {

global total done
incr total $bytes
if {($error ne "") || [chan eof $in]} {
set done $total
chan close $in
chan close $out
} else {
chan copy $in $out -size $chunk \
-command [list CopyMore $in $out $chunk]
} } set in [open $file1] set out [socket $server $port] set chunk 1024 set total 0 chan copy $in $out -size $chunk \
-command [list CopyMore $in $out $chunk] vwait done

The fourth example starts an asynchronous, bidirectional copy between two sockets. Those could also be pipes from two bidirectional pipelines (e.g., [open "|hal 9000" r+]); the conversation will remain essentially secret to the script, since all four chan event slots are busy, though any transforms that are chan pushed on the channels will be able to observe the passing traffic.

proc Done {dir args} {

global flows done
chan puts "$dir is over."
incr flows -1
if {$flows <= 0} {
set done 1
} } set flows 2 chan copy $sok1 $sok2 -command [list Done UP] chan copy $sok2 $sok1 -command [list Done DOWN] vwait done

SEE ALSO

close(3tcl), eof(3tcl), fblocked(3tcl), fconfigure(3tcl), fcopy(3tcl), file(3tcl), fileevent(3tcl), flush(3tcl), gets(3tcl), open(3tcl), puts(3tcl), read(3tcl), seek(3tcl), socket(3tcl), tell(3tcl), refchan(3tcl), transchan(3tcl), Tcl_StandardChannels(3tcl)

KEYWORDS

blocking, channel, end of file, events, input, non-blocking, offset, output, readable, seek, stdio, tell, writable

8.5 Tcl