File Operations

Top  Previous  Next

File operations allow you to read and write data to permanent storage devices such as a hard drive, floppy or removable media. They can also be used to send data to peripherals attached to your computer, such as a printer.

Opening files for reading and writing

The OPENFILE function initiates the connection between your program and the outside world. It has as syntax of:

Error =OPENFILE (Variable, filename, flags )

The variable must be either of type FILE for an ASCII file or BFILE to open the file in binary (raw) mode.

The flags parameter is a quoted string and can be one of "R" for reading, "W" for writing , "A" for appending to an existing file. For binary files the flags parameter can also be "R+" to open an existing file for both reading and writing.

The function will return 0 if the file was successfully opened or 1 if the file could not be created or opened. If the function fails you should not attempt to read or write to the fiel.

Appending opens the file, or creates it if it doesn't exist, and sets the file pointer to the end of the file (EOF). The W mode will create a new file, or empty an existing one, and set the file pointer to the beginning of the file. You are allowed to read from the file in both W and A modes.
 

DEF myfile as BFILE
IF OPENFILE(myfile, "C:\\temp\\temp.txt", "W") = 0
    WRITE myfile, 0xFFFF
    CLOSEFILE myfile
ENDIF

Closing open files

After you are finished reading or writing to a file you must close it to make sure that system resources are returned to Windows. If you leave too many files open at once you will receive an error message. Use the CLOSEFILE statement to close any open file.

Example:

OPENCONSOLE
DEF myfile:FILE
IF(OPENFILE(myfile,"C:\\EBASICTEST.TXT","W") = 0)
   WRITE myfile,"This is a test"
   CLOSEFILE myfile
   PRINT "File created successfully"
ELSE
   PRINT "File could not be created"
ENDIF
 
PRINT "Press Any Key To Close"
DO:UNTIL INKEY$ <> ""
CLOSECONSOLE
END

The previous example attempts to open a file for writing in the C:\ directory called "EBASICTEST.TXT". After opening the file, it writes one line of text to the file and then closes the file.

Writing to the file

In the example a new function was introduced, WRITE. WRITE returns 0 on success and can work with both binary and ASCII (text) files. WRITE expects two arguments, the variable initialized with OPENFILE and the data to be written.

How the data is written depends on whether or not an ASCII (FILE) variable or binary (BFILE) variable was used to open the file. In a binary file all data is written in raw form and will occupy the full size of the dimensioned variable. For example a standard STRING is 255 bytes:
 

DEF myfile as BFILE
DEF str as STRING
str = "hello"
IF OPENFILE(myfile, "C:\\temp\\temp.bin", "W") = 0
    WRITE myfile, str
    CLOSEFILE myfile
ENDIF

The length of the file will be 255 bytes in this case. However using an ASCII file the WRITE statement will only write the contents of the string and automatically terminate the string with a linefeed/carriage return pair.
 

DEF myfile as FILE
DEF str as STRING
str = "hello"
IF OPENFILE(myfile, "C:\\temp\\temp.txt", "W") = 0
    WRITE myfile, str
    CLOSEFILE myfile
ENDIF

The length of the file would be 7 bytes in this case and be loadable in any text editor.

Numeric data is also treated differently in ASCII and binary files. In binary mode numeric data is written in its raw form which occupies the same amount of bytes it would in memory. For example an INT variable is 4 bytes in memory and will be 4 bytes in a disk file written in binary mode. For an ASCII file the size depends on the number of decimal places specified by the SETPRECISION command
 

DEF myfile as BFILE
DEF iNum as INT
iNum = 3453423
IF OPENFILE(myfile, "C:\\temp\\temp.bin", "W") = 0
    WRITE myfile, iNum
    CLOSEFILE myfile
ENDIF

Would write 4 bytes to the file.
 

DEF myfile as FILE
DEF fNum as FLOAT
fNum = 3453423.3423
IF OPENFILE(myfile, "C:\\temp\\temp.txt", "W") = 0
    WRITE myfile, iNum
    CLOSEFILE myfile
ENDIF

The number of bytes written depends on the setting of SETPRECISION. The default is two decimal places. A space character is always written in ASCII mode following a numeric type to separate data and to allow reading a continuous stream of numbers using the READ function.

STRING types are always followed by a carriage return/line feed pair in ASCII mode. To combine separate strings on one line use concatenation or the APPEND$ function.

See Also: The Variables section for information on raw data sizes for all of the data types supported by EBASIC.

Reading from the file

Writing to files would not be of much use if we could not read what we wrote. The READ function returns 0 on success and has the syntax of:

Error = READ ( file, variable )

file must be a variable of type FILE or type BFILE and have been successfully initialized with the OPENFILE function. variable can be any built in type for ASCII files. Binary files also allow direct writing of UDTs.
 

OPENCONSOLE
DEF myfile:FILE
DEF ln:STRING
IF(OPENFILE(myfile,"C:\\EBASICTEST.TXT","R") = 0)
   IF(READ(myfile,ln) = 0)
            PRINT ln
   ENDIF
   CLOSEFILE myfile
   PRINT "File read successfully"
ELSE
   PRINT "File could not be opened"
ENDIF
PRINT "Press Any Key To Close"
DO:UNTIL INKEY$ <> ""
CLOSECONSOLE
END

When working with ASCII files the trailing carriage return/line feed character is not returned. Numeric data separated by any non numeric character can be read by continually calling the READ function and watching for the end of file with the EOF function.
 

DEF myfile as FILE
DEF flData as FLOAT
DEF flArray[12,100] as FLOAT
line = 0
IF(OPENFILE(myfile,"C:\\numerics.csv","R") = 0)
    'assume 12 entries per line
    WHILE EOF(myfile) = 0
        FOR x = 1 to 12
            IF READ(myfile, flData) = 0
                'do something with the data
                flarray[x-1, line] = flData
            ENDIF
        NEXT x
        line++
    ENDWHILE
    CLOSEFILE myfile
ENDIF

When working with binary files it is important to remember that READ will attempt to read as many bytes as required to fill in the variable. For numeric types this is dependant on the size of the type, an INT is 4 bytes for example. For STRING types READ will try and read the full dimension of the string, 255 bytes for normal strings. Arrays will be read/written to the full size of the array regardless of the index specified.

Determining the length of files

The LEN function works with file variables and returns the length of the open file in bytes.
 

Length = LEN (myfile )

Moving the file pointer

The SEEK command allows setting a binary file pointer to a position for reading or writing, it will not work with ASCII files. SEEK also allows obtaining the current file position.

SEEK filevariable, position

position = SEEK(filevariable)

Position specified the zero-based byte offset to begin reading or writing data. The second form of seek returns the current position.

Random Access Files

The READ and WRITE functions are known as sequential file operations. They read and write one piece of data at a time until the end of file is reached. For small files this is fine and very manageable. Lets consider, however, a very large file like an address book. If you have 200 names and addresses stored in a file and want to read the 125th name you would need to read 124 entries before you get to the one you want. Luckily, there is a better way.

The GET and PUT statements operate on a binary file using a record number as a parameter. Instead of having to access the 125th entry by reading the entire file you can get to that entry directly. The syntax of GET and PUT is:

GET filevariable, record, variable

PUT filevariable, record, variable

File variable must be of type BFILE. The variable to be written can be a user type (UDT) allowing complex records to be used. The record number must be greater than zero.
 

TYPE HighScoreTopTen
     DEF Score as INT
     DEF Time as INT
     DEF pname[20] as ISTRING
ENDTYPE
DEF TopTen as HighScoreTopTen
DEF myfile as BFILE
'…
IF(OPENFILE(myfile,"C:\\HIGHSCORES.DAT","W") = 0)
'…
TopTen.Score = 100
TopTen.Time = 25
TopTen.pname = "The Winner"
PUT myfile,7,TopTen

 

This would write the 7th record of the file with the contents of TopTen. The number of bytes written for each operation depends on the size of the UDT. You can determine the length of a UDT by using the LEN function with either the name of a defined UDT variable or the typename itself
 

DEF TopTen as HighScoreTopTen
filelen = 10 * LEN(HighScoreTopTen)

Copying files

Copies a file from a source directory to a destination. The syntax of COPYFILE is:

error = COPYFILE(source, dest, fail)

Source and destination are strings containing the full paths of the file to copy. If fail = 1 then the file will not be overwritten if it already exists in the destination directory. If fail = 0 then the file will be overwritten. COPYFILE returns 0 on error.

Deleting files

Deletes the specified file. The syntax of DELETEFILE is:

error = DELETEFILE(name)

Name is a string containing the full path to the file. DELETEFILE returns 0 if the file does not exist or is locked by another process.

Creating Directories

CREATEDIR is used to create a new directory under an existing one.

error  = CREATEDIR(name)

Name is a string containing the full path to the directory. The name should not end with a '\\' character. CREATEDIR returns 0 on error and cannot create multiple levels of new directories. Each level must be created individually.
 

IF CREATEDIR("c:\\My Programs")
    CREATEDIR("c:\\My Programs\\Samples")
ENDIF

Removing directories

REMOVEDIR is used to remove directories. The directory must be empty before it can be removed. The syntax of REMOVEDIR is:

error = REMOVEDIR(name)

Name is a string containing the full path to the directory. The name should not end with a '\\' character. REMOVE returns 0 on error.

Reading directories

FINDOPEN function

To read all of the file names in a directory use the FINDOPEN function to get a handle to the directory first. Once a directory is opened the names of the files can be obtained with the FINDNEXT function. The syntax of FINDOPEN is:

handle = FINDOPEN(directory)

Directory is a string the contains the full path to the directory plus any wildcard symbols for file matching. Example: "c:\\windows\\*.txt". handle is an integer variable. FINDOPEN returns 0 if the directory could not be opened for reading.

FINDNEXT function

After a directory is successfully opened with the FINDOPEN function use FINDNEXT to retrieve the filenames in a loop. FINDNEXT returns an empty string when all of the file names have been retrieved, an optional attribute parameter returns the files attributes. The syntax of FINDNEXT is:

name = FINDNEXT(handle {, attrib})

Handle is the integer value returned by FINDOPEN.

For a list of possible returned attributes see FINDNEXT in the alphabetical reference.

FINDCLOSE statement

After you are finished reading a directory you must close the handle with FINDCLOSE. If the handle is not closed memory loss will occur. The syntax of FINDCLOSE is:

FINDCLOSE handle

You must not close a handle more than once.
 
Example:

OPENCONSOLE
DEF dir:INT
DEF filename:STRING
 
dir = FINDOPEN("c:\\*.*")
IF(dir)
    DO
        filename = FINDNEXT(dir)
        PRINT filename
    UNTIL filename = ""
    FINDCLOSE dir
ENDIF
 
PRINT "Press Any Key"
DO:UNTIL INKEY$ <> ""
CLOSECONSOLE
END

Opening the system file dialog

FILEREQUEST opens a standard file dialog and returns a string containing the fully qualified pathname to the file.

Name$ = FILEREQUEST (prompt, parent, type {, filter} {,ext} {,flags} {,Initial Directory})

If type equals 1 then an ‘Open’ dialog is used. If type equals 0 then a ‘Save As’ dialog is opened. The optional filter variable limits the dialog to showing only certain file types. The string consists of ordered pairs separated by the '|' character and ending with two ||.

Example:

Filter$ = "Text files|*.txt|All Files|*.*||"

A default extension can be supplied in the optional ext parameter and will be used if the user does not type in an extension. This is a string parameter and should not contain the '.'

To allow users to select multiple files supply @MULTISELECT for the flags parameter. The returned string will contain complete paths to all of the files selected separated with the '|' character. If only one file is selected it will be terminated with the '|' character. The following example shows how to extract the filenames from the returned string:
 

REM Define a buffer to hold the returned filenames.
DEF filenames[10000]:ISTRING
DEF filter,filetemp:STRING
DEF pos:int
filter = "All Files (*.*)|*.*|Text Files (*.txt)|*.txt||"
 
filenames = filerequest("Select Multiple Files",0,1,filter,"txt",@MULTISELECT, "C:\\")
do
    pos = instr(filenames,"|")
    if(pos)
        filetemp = left$(filenames,pos-1)
        filenames = mid$(filenames,pos+1)
        REM do something with the file in filetemp
    endif
until pos = 0