Next: Self and super, Previous: Basic classes, Up: Top [Index]
This chapter describes how Ctalk performs basic file operations - opening, closing, reading, and writing files.
There are three classes that provide file input and output:
ReadFileStream, which implements objects and methods for
reading from files, WriteFileStream, which provides methods and
objects for writing to files, and their superclass, FileStream,
which provides methods and class definitions that are common to both
reading and writing files. There is also a DirectoryStream
class, which this chapter describes below.
Ctalk provides many of the same facilities that C’s stdio.h
library functions provide, although the language implements them as
objects.
Here is an example that shows how to use the openOn method
(class ReadFileStream).
ReadFileStream new myInput; myInput openOn "myFileName";
If the program was able to to open the file, you can then read input
from the myInput stream.
We should note here that Ctalk also provides classes and methods that
handle file I/O errors. We will deal with them later on. If you
need to see how to catch file I/O errors right now, look at some of
the example programs in the Ctalk package, especially ctwc.c.
Opening a file for output is similar to opening a file for input,
except that the stream is an instance of class WriteFileStream.
WriteFileStream new myOutput; myOutput openOn "outputFileName";
After a program has opened the file streams successfully, you can read and write from them with the following methods.
Operation Reading Writing --------- ------- ------- Read or write one character. readChar writeChar Read or write one line. readLine - Read or write all the data. readAll writeStream Read or write formatted data. readFormat printOn Read fixed length data. readRec
Here is a simple example that shows opening a file, and reading each character.
ReadFileStream new inputChars;
Character new c;
inputChars openOn "inputFileName";
while ((c = inputChars readChar) != EOF)
printf ("%c", c);
When readChar reaches the end of a file, it returns an
EOF character, which is ‘-1’ on most systems.
Using the method streamEof (class FileStream) to check for the
end of the input is slightly more reliable than looking for an
EOF character, because it distinguishes the end of the input
caused by an error from the end of the input caused by reaching the
end of a file.
ReadFileStream new inputChars;
Character new c;
inputChars openOn "inputFileName";
while (TRUE) { /* Loop until the end of the input. */
c = inputChars readChar;
if (inputChars streamEof)
break;
}
If you don’t need to examine each character as it is read, however,
then you can simply use readAll (class ReadFileStream),
which provides the complete input as a String object.
ReadFileStream new inputStream;
String new inputString;
inputStream openOn "myInput";
inputString = inputStream readAll;
printf ("%s", inputString);
Simple applications can use the methods readLine (class
ReadFileStream) and writeStream (class WriteFileStream)
together to process input.
Here is a portion of the program ctrep.c. You find the program in
the Ctalk package. It checks the input for occurrences of a character
string, and replaces the string before writing the output.
/*
* Loop until the end of input.
*/
while (TRUE) {
line = stdinStream readLine;
if (stdinStream streamEof)
break;
inputLineLength = line length;
word = "";
for (i = 0; i < inputLineLength; i = i + 1) {
inputChar = line at i;
if (inputChar isSpace) {
if (word == pattern) {
stdoutStream writeStream replacement;
} else {
stdoutStream writeStream word;
}
stdoutStream writeStream inputChar;
word = "";
} else {
word = word + inputChar asString;
}
}
}
Notice that the previous example used stdinStream and
stdoutStream as its input and output streams.
These two objects are class variables of ReadFileStream and
WriteFileStream, respectively. They represent the program’s
standard input (stdin) and standard output (stdout) file
streams.
Because ctrep.c is a filter program, it uses these two streams
instead of streams that work with normal files.
Class WriteFileStream also implements the stderrStream
class variable, which represents the application’s standard error
(stderr) stream.
You should notice, also, that most of the examples so far have used
printf to print output. You can accomplish the same task with
the following Ctalk statement.
stdoutStream writeStream "Hello, world!\n";
This is equivalent to:
printf ("Hello, world!\n");
Ctalk initializes stdinStream automatically when the program
creates the first ReadFileStream object, and it initializes
stdoutStream and stderrStream when the program creates
the first WriteFileStream object.
If the program simply needs to use stdinStream,
stdoutStream, or stderrStream without opening files,
then it can call the class method classInit with either the
class ReadFileStream or WriteFileStream as the receiver.
ReadFileStream classInit; /* Initialize stdinStream. */ WriteFileStream classInit; /* Initialize stdoutStream and stderrStream. */
Here is the example from the previous chapter that printed elements of
arrays. This version uses stdoutStream to output the array
elements.
Array instanceMethod printArrayElement (void) {
WriteFileStream classInit;
stdoutStream writeStream self;
return NULL;
}
int main () {
Array new myArray;
myArray atPut 0, "My";
myArray atPut 1, "name";
myArray atPut 2, "is";
myArray atPut 3, "Bill";
myArray map printArrayElement;
printf ("\n");
myArray atPut 3, "Joe";
myArray map printArrayElement;
printf ("\n");
}
The printArrayElement method initializes class
WriteFileStream. You need to perform the class initialization
before the class is first used in the program. There is no problem
with calling classInit multiple times, however, because the
method checks to determine if the class is already initialized.
The class DirectoryStream provides the methods mkDir and
rmDir which create and delete directories. The methods function
exactly as their C library counterparts, except that they raise a
SystemErrnoException on error and return an Integer with
the value -1.
Ctalk uses 0755 (‘drwxr-xr-x’) as the default mode for new
directories. Programs can change that value by redefining the macro
CTALK_DIRECTORY_MODE.
Here is a program that creates a new directory.
/*
* Define more restrictive permissions for
* new directories. Undefine the macro first
* to avoid a warning message.
*/
#undef CTALK_DIRECTORY_MODE
#define CTALK_DIRECTORY_MODE 0700
int main () {
DirectoryStream new thisDir;
thisDir mkDir "testDir";
}
The rmDir method works similarly to the mkDir method.
int main () {
DirectoryStream new thisDir;
thisDir rmDir "testDir";
}
The C99 standard requires that stdin, stdout,
and stderr should be implemented as macros, which on
some systems (notably Solaris) causes problems with
C-to-object translation.
If Ctalk cannot register the macros as C variables, then you
must call C functions like sscanf(3) and
fscanf(3) with only C variables, or use a method
with stdoutStream or stderrStream
(WriteFileStream class), or stdinStream
(ReadFileStream class).
The method consoleReadLine (in class String) prints a
prompt string, and then waits for you to enter a line of text. What
makes this method special is that it uses the GNU readline library’s
standard command editing and history features, if you built Ctalk with
readline support (see the options to the configure script for
details). In that case, Ctalk also defines the
HAVE_GNU_READLINE macro to ‘1’. Here is an simple example
of how to use consoleReadLine.
int main (int argc, char **argv) String new s;
String new promptStr;
if (argc > 1)
promptStr = argv[1];
else
promptStr = "Prompt ";
printf ("Readline test. Type ^C or, \"quit,\" to exit.\n");
#if HAVE_GNU_READLINE
printf ("Ctalk built with GNU Readline Support.\n");
#else
printf ("Ctalk built without GNU Readline Support.\n");
#endif
while (1) s consoleReadLine promptStr;
printf ("You typed (or recalled), \"%s.\"\n", s);
/*
* Matches both, "quit," and, "quit\n."
*/
if (s match "quit")
break;
}
}
Next: Self and super, Previous: Basic classes, Up: Top [Index]