Streams & Files
A stream is a cursor over a sequence (a collection, a file, a socket).
23.1 Streams
A stream is a cursor over a sequence (a collection, a file, a socket). Main classes: ReadStream, WriteStream, ReadWriteStream (all subclasses of PositionableStream).
23.2 Reading
Typical loop: [ stream atEnd ] whileFalse: [ words add: (stream upTo: $ ) ].
| rs |
rs := ReadStream on: #(1 2 3 4 5 6). "or: #(1 2 3 4 5 6) readStream"
rs next. "→ 1"
rs next: 2. "→ #(2 3)"
rs peek. "→ 4 (doesn't advance)"
rs skip: 1.
rs upToEnd. "→ #(5 6)"
rs atEnd. "→ true"
rs reset. "back to the start"
'name=Ada;age=36' readStream upTo: $=. "→ 'name'"23.3 Writing
print: writes an object's printString; << writes strings and the displayString of other objects (Pharo).
| ws |
ws := WriteStream on: (String new: 100).
ws nextPutAll: 'Hello'; nextPut: $,; space; print: 42; cr; tab; nextPutAll: 'done'.
ws contents. "→ 'Hello, 42
done'"
ws := WriteStream on: (Array new: 0).
ws nextPut: 1; nextPut: 2.
ws contents. "→ #(1 2)"
String streamContents: [ :s | s nextPutAll: 'abc'; print: 3 @ 4 ]. "→ 'abc(3@4)'"
Array streamContents: [ :s | 1 to: 3 do: [ :i | s nextPut: i squared ] ]. "→ #(1 4 9)"23.4 ReadWriteStream
| rws |
rws := ReadWriteStream on: String new.
rws nextPutAll: 'Smalltalk'.
rws reset.
rws next: 5. "→ 'Small'"23.5 Files with FileSystem
Pharo's FileSystem library models paths as FileReference objects:
| dir file |
"Roots: FileSystem workingDirectory, FileLocator home, FileLocator imageDirectory, FileLocator temp"
dir := FileLocator home / 'smalltalk-course'.
dir ensureCreateDirectory.
file := dir / 'notes.txt'. "the / message builds paths"
'notes.txt' asFileReference. "relative to the working directory"
"Write (delete first: writeStream overwrites from the start without truncating)"
file ensureDelete.
file writeStreamDo: [ :stream |
stream nextPutAll: 'First line'; cr; nextPutAll: 'Second line'; cr ].
"Read"
file contents. "→ the whole file as a String (UTF-8 decoded)"
file contents lines. "→ array of lines"
file readStreamDo: [ :stream |
[ stream atEnd ] whileFalse: [ Transcript show: stream nextLine; cr ] ].
"Inspect and manipulate"
file exists. file size. file basename. file extension. file parent. file isDirectory.
dir children. dir files. dir directories. dir filesMatching: '*.txt'.
dir allChildren select: [ :f | f extension = 'st' ].
file copyTo: dir / 'backup.txt'. file moveTo: dir / 'moved.txt'. (dir / 'moved.txt') delete.
dir deleteAll.
…23.6 In-memory file systems
Great for tests — no disk I/O:
| fs |
fs := FileSystem memory.
(fs root / 'a.txt') writeStreamDo: [ :s | s nextPutAll: 'in memory' ].
(fs root / 'a.txt') contents. "→ 'in memory'"23.7 CSV
Simple CSV: file contents lines collect: [ :line | line substrings: ',' ]. For robust CSV (quoting, escaping), use NeoCSV (NeoCSVReader on: stream).
23.8 Other dialects
Squeak uses FileDirectory and FileStream (FileStream fileNamed: 'x.txt' do: [...]), and also supports FileSystem in recent versions. GNU Smalltalk uses FileStream open: 'x.txt' mode: FileStream read and File name: 'x.txt'. VisualWorks uses 'x.txt' asFilename readStream.