How to work with the file system

Glamorous Toolkit, like any Smalltalk system, is built around an image. That does not mean it can't communicate with the outside world, like the file system. On the contrary. The file system is nicely modelled inside the image. For example, inspect this:

'.' asFileReference
  

This page described basic operations for working with files and directories.

Basic model

The class FileReference AbstractFileReference subclass: #FileReference instanceVariableNames: 'filesystem' classVariableNames: '' package: 'FileSystem-Core-Public' provides the main high-level API for working with files and folders. It holds a Path Object variableSubclass: #Path instanceVariableNames: '' classVariableNames: '' package: 'FileSystem-Path-Base' and a FileSystem Object subclass: #FileSystem instanceVariableNames: 'store' classVariableNames: '' package: 'FileSystem-Core-Public' and can manipulate File Object subclass: #File instanceVariableNames: 'name' classVariableNames: 'Registry S_IFBLK S_IFCHR S_IFDIR S_IFIFO S_IFLNK S_IFMT S_IFREG S_IFSOCK' package: 'Files-Core' objects, which provide the basic set of operations for working files on disk.

A Path Object variableSubclass: #Path instanceVariableNames: '' classVariableNames: '' package: 'FileSystem-Path-Base' abstracts locations on the file system, and can be relative or absolute. FileSystem Object subclass: #FileSystem instanceVariableNames: 'store' classVariableNames: '' package: 'FileSystem-Core-Public' defind protocol for interacting with filesystems. It hold a reference to a concrete store (a subinstance of FileSystemStore Object subclass: #FileSystemStore instanceVariableNames: '' classVariableNames: '' package: 'FileSystem-Core-Kernel' ) where files are saved; this can be on disk (DiskStore FileSystemStore subclass: #DiskStore instanceVariableNames: 'maxFileNameLength' classVariableNames: 'CurrentFS DefaultWorkingDirectory' package: 'FileSystem-Disk-Store' ) or in memory (MemoryStore FileSystemStore subclass: #MemoryStore instanceVariableNames: 'root' classVariableNames: 'CurrentFS' package: 'FileSystem-Memory-Store' ).

Writing to a text file

The method AbstractFileReference>>#writeStreamDo: writeStreamDo: aBlock | stream | stream := self writeStream. ^ [ aBlock value: stream ] ensure: [ stream close ] writes to a file using a utf8-encoded buffered character stream. It gets the stream as a parameter, and makes sure the stream gets closed after writting is done.

textFile := './example.txt' asFileReference.
textFile writeStreamDo: [ :aStream | 
	aStream nextPutAll: 'Content in a text file' ].
textFile
  

Reading from a text file

The method AbstractFileReference>>#readStreamDo: readStreamDo: aBlock | stream | stream := self readStream. ^ [ aBlock value: stream ] ensure: [ stream close ] reads the content of a text file using a utf8-encoded buffered character stream.

textFile := './example.txt' asFileReference.
contents := nil.
textFile readStreamDo: [ :aStream | 
	contents := aStream contents ].
contents
  

A stream allows us to read the content in chunks. In case we are simply interested in the entire content we can use AbstractFileReference>>#contents contents self readStreamDo: [ :stream | ^ stream contents ] .

textFile := './example.txt' asFileReference.
contents := textFile contents