Streams offer a means to sequentially access elements of a collection. Technically they are statefull objects, holding on a collection or file-handle, and a position. The position is advanced when reading/writing. In addition to internal streams (which operate on a collection), there are also external streams to access files, directories, pipes or sockets.
The most useful stream classes are:
External streams only support byte-sized elements. These must be either small integers (0..255) or characters in the single-byte range.
aStream := ReadStream on:aCollection
or:
aCollection readStream
aStream atEnd ifTrue:[ ... ]
nextElement := aStream next
aCollection := aStream next:count
aStream skip
aStream skip:count
Integer readFrom:aStream
Integer readFrom:aStream onError:[...]
Float readFrom:aStream
Float readFrom:aStream onError:[...]
Number readFrom:aStream
Number readFrom:aStream onError:[...]
formatString scanf:readStream
|string stream word1 word2 num1 num2 num3|
string := 'one two 12345 567.678'.
stream := string readStream.
word1 := stream nextAlphaNumericWord.
stream skipSeparators.
word2 := stream upToSeparator.
num1 := Number readFrom:stream.
num2 := Number readFrom:stream.
num3 := Number readFrom:stream onError:[ 'NothingMore' ].
Transcript showCR:word1.
Transcript showCR:word2.
Transcript showCR:num1.
Transcript showCR:num2.
Transcript showCR:num3.
notice, that there are other ways to perform the above;
tokenization could also be done with:
|string words word1 word2 num1 num2 num3|
string := 'one two 12345 567.678'.
words := string asCollectionOfWords.
word1 := words first.
word2 := words at:2.
num1 := Number readFrom:(words third).
num2 := Number readFrom:(words at:4).
num3 := Number readFrom:(words at:5 ifAbsent:nil) onError:[ 'NothingMore' ].
Transcript showCR:word1.
Transcript showCR:word2.
Transcript showCR:num1.
Transcript showCR:num2.
Transcript showCR:num3.
More details are found in the
"ReadStream
class documentation".
aStream := WriteStream on:aCollection
aCollection writeStream
aStream nextPut:nextElement
aStream next:count put:nextElement
aStream nextPutAll:aCollection
collection := aStream contents
More details are found in the
"WriteStream
class documentation".
FileStream
, PipeStream
,
Socket
and DirectoryStream
.
aStream nextPut:aCharacter
aStream nextPut:aByteValueInteger
aStream nextPutByte:aByteValueInteger
aStream nextPutAll:aCollection
aStream cr
aStream next
aStream nextLine
aStream next:howMany
aStream binary
aStream text
aStream nextPutBytes:count from:aByteCollection startingAt:indexOfFirstByte
aStream nextBytes:count into:aByteCollection startingAt:indexOfFirstByte
nextPut:
-like messages, and return small integer
values in all next
-like messages.
|s bytes|
s := 'patches' asFilename readStream.
s binary.
bytes := s next:5.
s close.
bytes inspect.
Also, there a methods to read and write low-level machine objects,
such as 2,4 and 8-byte integers.
These can be processed both in least-significant-byte-first (LSB) or most-significant-byte-first (MSB)
order.
aStream nextPutShort:aNumber MSB:msbFlag
aStream nextPutLong:aNumber MSB:msbFlag
aStream nextShortMSB:msbFlag
aStream nextUnsignedShortMSB:msbFlag
aStream nextLongMSB:msbFlag
aStream nextUnsignedLongMSB:msbFlag
More details are found in the
"ExternalStream
class documentation".
aStream := FileStream readonlyFileNamed:aFilenameString
aStream := FileStream oldFileNamed:aFilenameString
aStream := FileStream newFileNamed:aFilenameString
Filename
to create fileStreams:
aStream := aFilenameString asFilename readStream
aStream := aFilenameString asFilename readWriteStream
aStream := aFilenameString asFilename writeStream
aStream := aFilenameString asFilename appendingWriteStream
|lines|
lines := 'smalltalk.rc' asFilename contents.
or a single (big) string:
|bigString|
bigString := 'smalltalk.rc' asFilename contents asString.
If the file is big, you may want to enumerate byte-blocks with
|stream eachLine block|
stream := 'stx.exe' asFilename readStream.
[stream atEnd] whileFalse:[
block := stream nextBytes:(8*1024).
"/ do something with block here; the last one might be smaller than 8k
Transcript showCR:block size.
].
stream close.
or enumerate individual lines with:
|stream eachLine|
stream := 'smalltalk.rc' asFilename readStream.
[stream atEnd] whileFalse:[
eachLine := stream nextLine.
"/ do something with line here
].
stream close.
of course, linewise enumeration is also possible in the above (reading all first) case:
|lines|
lines := 'smalltalk.rc' asFilename contents.
lines do:[:eachLine |
"/ do something with eachLine here
].
|stream eachLine|
stream := 'newFile' asFilename writeStream.
stream nextPutLine:'hello - this is line1'.
stream nextPutAll:'this is line2'.
stream spaces:8.
stream nextPutAll:'more into line2'.
stream cr.
stream nextPutLine:'this is line3'.
stream cr.
stream cr.
stream cr.
stream close.
More details are found in the
"FileStream
class documentation" or
"Filename's
class documentation".
aStream := PipeStream readingFrom:aCommandString
aStream := PipeStream writingTo:aCommandString
"who"
UNIX command:
|s line|
s := PipeStream readingFrom:'who'.
[(line := s nextLine) notNil] whileTrue:[
Transcript showCR:line
].
s close
More details are found in the
"PipeStream
class documentation".
aSocketStream := Socket provide:aService
where aService is either a port number or a service name
"/etc/services"
file.
aSocketStream := Socket connectTo:aService on:aHostName
See examples in the "doc/coding"
directory for more details.
More details are found in the
"Socket
class documentation".
Copyright © 1996 Claus Gittinger Development & Consulting
<info@exept.de>