How to Read or Write a text file with a Stream

From Cuis CookBook
Jump to navigation Jump to search

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