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'))