Version 46 of chan

Updated 2008-12-23 20:32:24 by lars_h

chan - Manipulate channels

http://purl.org/tcl/home/man/tcl8.5/TclCmd/chan.htm

chan option ?arg arg ...?

See Also

This command (introduced in Tcl 8.5) provides several operations on a channel, including many that have been available using a mix of other commands. Option indicates what to do with the channel. Any unique abbreviation for option is acceptable. The valid options are: (see the man page listed above for more details; on this web page, notes on selected options have been contributed).

chan action ?arg arg ...?

Why was this thing called 'chan' instead of 'channel'? schlenk: It's mentioned in the TIP [L1 ], basically the same naming style as interp for interpreter.

TIP 208
add chan

I see. Thank you for pointing that out. Pretty lame reasoning when "channel" is much more descriptive. But I'm not the one doing all the work so I'm not complaining!

JYL If you dont like chan you can do 'interp alias {} channel {} chan'

AMG: chan aggregates all the commands you'll need for working with chan blocked channelId - like fblocked

chan close channelId - like close

chan configure channelId ?optionName? ?value? ?optionName value?... - like fconfigure

chan copy inputChan outputChan ?options...? - same as fcopy

chan create mode cmdPrefix

chan eof channelId - like eof

chan event channelId event ?script? - like fileevent

chan flush channelId - like flush

chan gets channelId ?varName? - like gets

chan names ?globPattern? - like file channels

chan pending mode channelId - returns the number of bytes (of input or output, depending on mode) buffered internally

chan pop channelId - pop one transform off a stacked channel

chan postevent channelId eventSpec

chan push channelId cmdPrefix - stack a transform on top of the channel

chan pipe - create a standalone pipe and return a pair of file descriptors for its read and write ends, in this order (TIP #304 [L2 ], available in Tcl >= 8.6).

chan puts ?-nonewline? ?channelId? string - like puts

chan read channelId ?numChars? - like read

chan read ?-nonewline? channelId -like read

chan seek channelId offset ?origin? - like seek

chan tell channelId - like tell

chan truncate channelId ?length?


TIP 287 proposes a [chan available channelId] command to find out how much available input is currently being buffered that could be chan read in. (It would make it safe to use chan gets with sockets since you could introspect and detect someone sending an excessively long line rather than running out of memory first.)

See also chan mode for an example how to extend that ensemble.


RS History sometimes runs in circles... Tcl 2.1 didn't have commands dealing with channels. Peter da Silva added the "stream" extension, where one could write

  stream fp open $filename r
  set x [stream fp gets]
  stream fp close

Later, the parts of "stream" went into the core as separate commands. Still later (in 8.5), they get reunited again in chan, which arguably makes the command set leaner, but scripts wordier...


MG has just needed to find out how long the eol sequence in a particular file was. Checking fconfigure $fid -translation didn't help (as it was just 'auto' on the read, and always crlf (Win XP) on the write, even if the file used Unix line-endings). Came up with this (which is possibly obvious, but I'm rather pleased with myself anyway;)

proc lineEndingSize {file} {
    set fid [open $file r]
    chan gets $fid line
    set size [expr { [chan tell $fid] - [string bytelength $line] }]
    close $fid
    return $size;
}

DKF: That can go wrong. The problem is that you need to use the encoded length of the string read, and some encodings have multiple ways of encoding a particular character. This is all rather nasty; even guessing based on the value of fconfigure -encoding can go wrong! So instead try this:

proc lineEndingSize file {
   set f [open $file]
   gets $f line
   set after [tell $f]
   seek $f 0
   read $f [string length $line]
   set before [tell $f]
   close $f
   return [expr {$after - $before}]
}

MG I'll try that instead, thanks :)