Working with Files

initsd()
ferror()
fileexists()
loc()
lof()
currentcard()
openfile()
closefile
read$()
fget()
fput
write$
readsec()
writesec

File access, reading from and writing to files is provided through this interface. Files reside on either SD card ‘a:’ or SD card ‘b:’. Programmatically card ‘a:’ is 0 and card ‘b:’ is 1 

initsd()
initsd(<card 0 or 1>)
a=initsd(1)

Initialises SD card 0 or SD Card 1, this may be called ‘mount’ in some systems. It checks to see if the card exists and associates an internal media descriptor with that card. This keyword is not needed for any of the file system keywords as they do this anyway.

Some cards may not have a file system on them or the user may want to devise their own. It has been provided in case direct manipulation of the card is required, i.e. reading / writing sectirs. This keyword returns 0 if the command was unsuccessful or 1 otherwise.

ferror()
a=ferror()
print ferror()

Returns the latest file error if any. This will return 0 if there have been no file errors. This keyword is also used for detecting the end of file or checking file operations.

Error Description
0 The last file operation was successful
22 Card is not present
23 Card is not FAT16
24 Sector error when establishing the details from the MBR
25 Boot record has an invalid signature
26 Media has not been mounted
27 File not found
28 File not open
30 End of file
31 Invalid cluster, probably an attempt to read a cluster beyond the end of the card
32 Root directory full (subdirectories only limited by available space)
35 Cannot mount the card
38 Not a valid file mode, ‘w’,’r’ or ‘a’
42 Can’t read a requested sector
46 Can’t write a requested sector
47 No free files available, most likely result of this error is not closing a file after use.
48 Attempt made to read past end of media
50 Can’t create a file because it already exists
51 Run out of short file names
52 Subdirectory not empty, usually when trying to remove it
53 Unknown error when trying to write
54 Unknown error when trying to read

fileexists()
fileexists(“<filename>”)
a=fileexists(“inp.bas”)
b=fileexists(a$)

Tests for the existence of a file, the filename should be either in the current directory or the full path should be given, i.e. “b:\sub1\inp.bas”.

It returns 1 if it exists and 0 if not.

loc()
loc(<file number>)
a=loc(fn)

Returns the current position in a file. The position is where the next data will be read or written to. Setting the file position is done in the read and write keywords.

lof()
fsize(<file number>)
a=lof(fn)

Returns the size of the open file in bytes.

currentcard()
currentcard()
a=currentcard()
print currentcard()

Returns an integer which is the current mounted card, Card ‘a:’ is 0, ‘b:’ is 1 etc. If there is no card mounted it returns -1.

openfile()
openfile(<filename><mode>)
fn=openfile(“fred”,’w’)
fn=openfile("b:\sub1\bob.txt", 'a')

The file open operation associates a file number, in the above case stored in variable ‘a’, with a file name and mode. The file number is an integer between 1 and 4. A value of 0 means that the operation was unsuccessful, the reason will be in ferror().

The following modes are available

Mode Description
r For reading only, writing is not allowed. The file must exist
w This will delete an existing file and create a new one. Data written to the file will start at the beginning
a The file must exists. Data will be appended to the existing file and the file can also be read. NOTE that the position is set to the end of the file, so to read from the beginning the position needs to be moved, see read and write$

It is important when writing data to a file that the file is closed. This action will flush the buffers and update the file size and date.

closefile
closefile <file number>
closefile fn

Closes a previously opened file. This releases the file number for use in other files so it is important to close a file after use. When a file is opened for reading this is the only consequence of not closing a file. However if a file is written to the contents may not actually get written until the file is closed and the file size and date will not get updated causing possible corruption of the file.

read$()
read$(<fn>,max)
a$=read$(fn,12)
b$=read$(fn,max)

Read string: This will read a string from the open file into the supplied sting variable. A string is a set of characters terminated by a zero. It will continue to read the file until either a 0 is encountered or the maximum number of characters is read. The file position is incremented to the end of the string so that a subsequent read string will get the next string in the file.

As ‘openfile’ for read (‘r’) sets the position to the beginning of the file if this is called just after file open the first string in the file is obtained.

fget()
fget(<fn>[;start],buffer,length)
a=fget(fn,buf%,12)
b=fget(fn;531,buf%,32)
c=fget(fn,adr(a$),20

File get: this is a more comprehensive file read than ‘read$’ as it will read anything from the file not just strings. It needs to be supplied with an address to RAM rather than a string, this is obtained by getting the address of a variable, some examples:

buf%=adr(a$)
buf%=adr(t&[1])
buf%=0xa0002500

The latter example assumes that the address given is in RAM, if not an exception error will occur. The length is the number of bytes requested, if the end of file is encountered then that number of bytes will not be returned, only those bytes up to the end of the file. The statement ‘fget’ will return the actual number of bytes read and in addition to ‘ferror’ this could be checked against the requested bytes in order to detect the end of the file.

By default ‘fget’ will read from the beginning of the file if it has been opened with ‘r’ or from the end of the file if it has been opened with ‘a’. By using a semicolon and a number (which can be a variable) the start position can be specified. This is the number of bytes from the beginning of the file.

fput
fput <fn>[;start],buffer,length
fput fn buf%,12
fput fn;531 buf%,32

File put: the opposite to file get, this also works with a buffer address. The file must first be opened for append or write and by default the writing takes place at the beginning of the file if it has been opened with ‘w’ or the end of the file if it has been opened with ‘a’.

The write position can be specified by using a semicolon after the file number and specifying an offset in bytes from the beginning of the file. The file will be automatically expanded to accommodate the new start address and/or the length.

write$
write$ fn[;start] string,string,....
write$ fn a$
write$ fn a$,b$
write$ fn;32 a$,*13
write$ fn a,b,c#

Write string: this is for working with files and strings although in the last example two integers and a floating point value have been used. These will be converted to stings and saved as a sting. The third example uses a character constant ‘*13’ which will but a byte with a value of 13 into the file. Because #13 is Carriage Return this is effectively a write line function.

As in the ‘fput’ command writing will commence at the beginning of the file if the file has been opened with ‘w’ or at the end of the file if opened with ‘a’. This can be overridden with an optional start position that follows the file number.

readsec()
readsec(<card>,<sector>,<buffer>)
a=readsec(0,7321,x%)
b=readsec(card,sec,buf%)

Read sector: Some SD Cards may not have a file system on them in which case it will not be possible to open a file. This along with ‘writesec’ provides direct access to the sectors on the SD Card. The only proviso is that the card has sectors of 512 bytes, which most do.

The statement returns 1 on success and 0 on failure. ‘ferror()’ can be examined to find the cause of the failure. The card is an integer; 0 for the first and 1 for the second card. Sector is also an integer and the buffer is an address of RAM or a variable to store the data in.

If a card has no filing system or it is corrupt then the normal ‘openfile’, ‘read’ etc. commands will not work. This command will still however work because it reads the Card sectors directly. The card may need initialising first with ‘initsd’.

writesec()
writesec(<card>,<sector>,<buffer>)
a=writesec(0,7321,x%)
b=writesec(card,sec,buf%)

Write sector: writes a sector to the SD Card, see also ‘readsec’. WARNING writing a sector to a card with a filing system is likely to corrupt it, if you must, choose a sector that is beyond the directory and FAT. A sector that is likely to clear these two will be say greater than 2000, a 1GB card has almost 2,000,000 sectors so there is plenty to go at.