How to Read or Write a text file with a Stream
FileEntry
class has four high-level methods for accessing a file using a stream:
readStreamDo: aBlock
: read from file using a stream.writeStreamDo: aBlock
: write to file using a stream.appendStreamDo: aBlock
: append to file using a stream.forceWriteStreamDo: aBlock
: write to file using a stream, overwriting the current file if it exists.
For all of them, the block parameter receives a stream on the file contents, and they open and close the file stream.
Let's see how these work in an example.
Problem
Write data to a file in Comma Separated Values (CSV) form.
Solution
Use writeStreamDo:
to create a file, obtain a stream and use the stream api to write to the file:
| data | data _ {{'foo'. 22}. {'bar'. 44}. {'baz'. 64}}. 'data.csv' asFileEntry writeStreamDo: [:fileStream | data do: [:item | item allButLast do: [:value | fileStream nextPutAll: value asString; nextPut: $,]. fileStream nextPutAll: item last asString; newLine]].
We use the usual stream api for writing to the file: #nextPutAll:
, #nextPut:
and #newLine
.
The result of this is a data.csv
file with the following contents:
foo,22
bar,44
baz,64
Problem
Read the data back from our CSV file.
Solution
Use readStreamDo:
method to obtain a read stream on the file:
| data | data _ OrderedCollection new. 'data.csv' asFileEntry readStreamDo: [:fileStream | [fileStream atEnd] whileFalse: [ |line| line _ fileStream nextLine. data add: (line subStrings: (Array with: $,))]].
For the read stream interface, we used #atEnd
and #nextLine
for reading line by line.
The result is the CSV data in a Collection: an OrderedCollection(#('foo' '22') #('bar' '44') #('baz' '64'))