Writing To and Reading From Files

Discussed in this topic: fd.getdata, fd.setdata, fd.pointer, fd.setpointer, fd.filesize.

Writing to and reading from files are two most important file operations. Having a flash disk would be pointless without them. Writing and reading is done using two methods — fd.setdata and fd.getdata respectively. For these to work, the file must first be opened. Fd.setdata and fd.getdata work on the currently selected file, and the selection is made through the fd.filenum property.

The pointer

Both reading and writing operations are always performed from the current pointer position. This position can be checked through the fd.pointer R/O property and changed through the fd.setpointer method. Executing the fd.setdata or fd.getdata moves the pointer forward by the number of file positions written or read.

The pointer always points at the position (offset) in the file from which the next reading or writing will be done. File offsets are counted from one, not zero. The very first byte in the file is at offset one, the next byte — at offset two, and so on. The very last byte in the file is at offset equal to the size of the file, which is indicated by the fd.filesize R/O property. The maximum pointer value, however, is fd.filesize+1! When the pointer is at maximum, it effectively points at the file position that doesn't yet exist. So, writing to the file at this position will append new data to the end of the file. Writing to the file when the pointer is not at the maximum will overwrite existing data.

When the file is opened, the pointer is set to 1 if the file has any data in it (fd.filesize<>0), or 0 if the file is empty (fd.filesize=0). It is not possible to set the pointer to zero if the file is not empty. The pointer will be moved automatically if the file becomes smaller and will be set to zero if the file becomes empty.

Writing and reading

In the following example, we append the data to the end of the file, then read the data from the beginning of the file:

** Tibbo Basic **

Dim s As String

'open a file 'on' file number 3
fd.setpointer(fd.filesize+1) 'works always -- no matter whether the file is empty or not
fd.setdata("Append this to the file")
fd.setpointer(1) 'go back to the beginning of the file
s=fd.getdata(10) 'read 10 bytes from the beginning of the file

If fd.setdata is executed when the pointer isn't at the end of the file (at fd.filesize+1 position) then some of the existing file data will be partially overwritten. If the pointer moves past the current file size (see.filesize), the size will be increased automatically. As you append new data to the file, the file will grow larger. New data sectors will be allocated and added to the file automatically as needed. You will get the 7- PL_FD_STATUS_DATA_FULL error if the disk runs out of free sectors. When the fd.setdata is executed and the disk full condition is detected, the entire data string supplied with fd.setdata is not saved into the file (and not just the part that couldn't fit).

Fd.setdata makes changes to the sectors of the flash disk. For the highest possible reliability, use disk transactions when invoking this method.

File data caching

The fd. object uses the RAM buffer #1 as an intermediary storage for the sector's data. When you access a certain data sector, the contents of this sector are loaded into the RAM buffer #1. When you change the data in the sector, it is the data in the RAM buffer that gets changed. The changed contents of the RAM buffer will not be saved back to the flash memory until the contents of another sector must be loaded into the buffer. So, for example, if you do this...

** Tibbo Basic **

fd.setdata("Write this to a file")

... and then leave the disk alone, then the new data may stay in the RAM buffer indefinitely. It may get lost — for example, if you reboot the device. To prevent this, close the file or use the fd.flush method — either one will cause the changed data in the RAM buffer to be saved back to the flash memory. Note that the fd.flush method does not depend on the current fd.filenum value and works globally on any most recently changed file.

It is not necessary to use fd.flush if your disk operations are performed within a disk transaction.