- Up - | Next >> |
The basic idea of how to use files in Mozart is as follows. We provide a class Open.file
. To an object created from this class we refer to as file object. Conceptually, its state consists of a string together with the current position in this string called seek pointer.
In the following, we will refer to this particular string as file. It is visible to other operating system processes via the operating system's filesystem.
The atoms used for labels and fields of methods of the class Open.file
are chosen to coincide with the common operating system terminology (i. e., POSIX terminology).
Suppose we want to read data from a file named a.txt
. The contents of this file is as follows1:
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | |
---|---|---|---|---|---|---|---|---|---|---|
0 | H | e | l | l | o | H | e | l | l | o |
10 | O | z | _ | I | s | _ | b | e | a | u |
20 | t | i | f | u | l |
The first step is to create a file object and associate it to the file a.txt
. This is done by feeding
F={New Open.file init(name:'a.txt' flags:[read])}
The list [read]
used as value of the field flags
means that we want to have read access to the file.
After the file has been opened and associated to the file object F
, we can read from it. To read the next five characters from the file we feed
{F read(list:{Browse} size:5)}
The character string Hello
appears in the browser window (the value 5
at the field size
signals that we want to read five characters from the file).
Note that if we had not switched the browser to the mode for displaying virtual strings (see Chapter 2), we would have seen the output [72 101 108 108 111]
in the browser window.
A common pattern of use is to read the entire file into an Oz string. This is especially supported. Feed:
{F read(list:{Browse} size:all)}
The rest of the file HelloOz is beautiful
appears in the browser window.
Up to now we have read the data in strict left to right fashion. Suppose we want to start reading at the eighth character of the file. Navigating to this character and reading the following five characters is done by:
{F seek(whence:set offset:7)}
{F read(list:{Browse} size:5)}
You will see lloOz
in the browser window. Internally, as already mentioned, each file object has a seek pointer. Each operation refers to its position: for instance, instead of ``reading five characters'' one should think of ``reading the next five characters after the seek pointer''. Note that in order to read the first character of a file, the seek pointer must be set to the offset zero.
Furthermore, you can get the current position of the seek pointer by:
{F tell(offset:{Browse})}
The number 12
appears in the browser window.
After use, the file object F
must be closed. By applying F
to the message close
:
{F close}
the file as well as the file object are closed. Note that invoking a method other than close
of the class Open.file
after the object has been closed raises an exception. Exceptions are discussed later.
Suppose we want to create an object for a file which does not yet exist and that should be named ours.txt
. Furthermore, this file should have read and write access rights for yourself and for each member of your group. We feed
F={New Open.file
init(name: 'ours.txt'
flags: [write create]
mode: mode(owner: [read write]
group: [read write]))}
Data to be written to the file must be virtual strings. For example, the character sequence "Go ahead"
can be written to the file F
by
{F write(vs:'Go ahead!')}
The same character sequence we also can write by
{F write(vs:"Go ahead!")}
Also more complex virtual strings are handled this way. For example
{F write(vs:"This is "#1#' And '#
("now a float: "#2.0)#"\n")}
writes a nested virtual string containing integers, atoms, strings and floats to the file. Even the filename argument of the init
method of class Open.file
is allowed to be a virtual string. For more information on virtual strings see Section 2.2.
If you type the Unix command
cat
ours.txt
or the Windows command
type ours.txt
to a shell, you see the content of ours.txt
printed to standard output.
Functionality provided by the class Open.file
relies on operating system services. These services might report exceptions, these exceptions are then raised as Oz exceptions.
For example, trying to open a non existing file raises an exception. Operating system dependent exceptions can be caught as follows:
try
_={New Open.file init(name:'not-existing')}
catch system(os(A W I S) ...) then
{Browse os(category: A
what: W
number: I
description: S)}
end
where A
is an atom describing the category of the error (e. g., os
or host
), W
the system call that raised the exception (as string), I
is the operating system dependent error number, and S
is a string describing the error.
Besides of operating system exceptions, the methods of the class Open.file
can raise two different exceptions themselves:
An exception is raised when an object is initialized twice. This exception can be caught as follows:
try
...
% Initialize twice
...
catch system(open(alreadyInitialized O M) ...) then
end
Here O
is the object that has been tried to be initialized twice by applying it to the method M
.
An exception is raised when a message other than close
is executed by an already closed file object. This exception can be caught as follows:
try
...
% Apply closed object
...
catch system(open(alreadyClosed O M) ...) then
end
Here O
is the object that has been closed already and M
the message O
has been applied to.
- Up - | Next >> |