File Input/Output

PCC provides commands for simple file I/O. You can read and write text and binary files.

 File Handles

Like in almost all programming languages, files have to be "opened" before they can be used (see `Open'). When opening the file, you must specify the file name, intended access mode, and a file handle. The file handle is a number between 1 and 20 and is used later on when referring to the file. It is up to you to assign file handles.

By convention, file handles are specified with a leading hash sign, but this is optional except for `Print'.

Example:

  Open "log.txt" For Append As #17
  Print #17, "I play ", My.Race, " in ", System.GameDirectory
  Close #17

Here, the `#' signs at `Open' and `Close' are optional, the one at `Print' is needed.

File handles are global, like shared variables. They do not survive PCC exit and reload, and all that. You can not assume that you can open a file, suspend, and later on continue using that file!

The `FreeFile' function can be used to obtain a file handle which is not currently in use. The above example could be rewritten as

  Local fd := FreeFile()
  Open "log.txt" For Append As #fd
  Print #fd, "I play ", My.Race, " in ", System.GameDirectory
  Close #fd

This way it does not interfere with other scripts which may have file handle #17 already open.

 File Pointer

For each file handle, there is a file pointer. The file pointer describes where input and output happens in the file. Usually, it starts at the beginning of the file with a value of zero (unless the file was opened in `Append' mode), and all input/output operations advance it by the number of bytes written.

Related functions: Seek, FPos(#fd), FSize(#fd)

 Text Files

There's no direct distinction between text and binary files. You can safely mix binary and text file I/O, but I do not recommend that.

You can read and write text files line by line using the `Input' and `Print' commands. Although you can use the file pointer commands on text files, the text file functions are optimized for linear access. The `Seek' command has only a limited use, anyway: you can use it to seek back to a position you got with `FPos(#fd)' to read something again, but you can not in general, for example, overwrite a line with something else, or directly jump to line number this'n'that with `Seek'.

 Binary Files

Binary I/O works as follows. When you want to read something, you read it into a block, which you can then take apart using the `GetXXX' functions. Block sizes can be in the range 1 to 255.

Let's assume you want to read PCC's score statistics file. It starts with a 12 byte header:

  Dim header, length, item
  Open "stat.cc" For Input As #1
  Get #1, header, 12

Now, `header' contains the header. You can now extract data items from it:

  Print GetWord(header, 8), " entries in file"

Here, `GetWord' extracts the word (16-byte signed integer) at position 8. Other functions to extract data items are `GetByte', `GetLong', and `GetStr'.

You can now read more data blocks; they need not have the same size as the first one. For example, in PCC's score stat files, the length of a data item is in the header at offset 10.

  length := GetWord(header, 10)
  Get #1, item, length

Now, `item' contains the first score record.

Writing binary files is similar. You start by defining a variable which will receive the data block.

  Dim block

To store data in it, use the `SetXXX' commands:

  SetWord block, 0, 1234

stores the value 1234 at offset 0 in the data block. To write such a block to the file, use `Put':

  Put #2, block, 100

writes 100 bytes.

 Pitfalls

I do not recommend mixing binary and text I/O. This does not mean it would be unsafe -- it's just confusing to the programmer ;-)

The `GetXXX' and `SetXXX' operations ought to be the only operations allowed on data blocks. Right now, data blocks are just ordinary strings so you can use all the other string operations on them; but that may change in the future.

File I/O is buffered (or, is intended to be - right now, only text reads are buffered). If you open the same file on multiple file handles, and modify it through one, read it through the other, you may not get the results you expect (reading and writing through the SAME file handle is okay, though).

Switching between read and write, and manipulating the file pointer, degrades buffering efficiency.


[ << Previous | Up | Next >> ]

Stefan Reuther <Streu@gmx.de>