# Working With Files On Unix and Windows systems RETRO provides a set of words for working with files. As a pragmatic choice these are mostly modeled after the file functions in libc. The file words are in the `file:` namespace. ## File Access Modes You can open a file for various operations. The functionality allowed depends on the file access mode. Valid modes in RETRO are: file:A Open for appending; file pointer set to end of file file:R Open for reading; file pointer set to start of file file:R+ Open for reading and writing file:W Open for writing ## Opening A File To open a file, pass the file name and a file mode to `file:open`. '/etc/motd file:R file:open On a successful open this will return a file handle greater than zero. Additionally, RETRO provides a few other forms for opening files. To open a file for reading: '/etc/motd file:open-for-reading This will return the size of the file (as NOS) and the file handle (as TOS). To open a file for writing: '/tmp/test file:open-for-writing This returns the file handle. To open a file for append operations: '/tmp/test file:open-for-append As with `file:open-for-reading`, this returns both the size of the file and the file handle. ## Closing A File To close a file, pass the file handle to `file:close`. '/etc/motd file:A file:open file:close ## Reading From A File To read a byte from an open file, pass the file handle to the `file:read` word. @FID file:read n:put To read a line from a file, pass the file handle to the word `file:read-line`. @FID file:read-line s:put The line is read into a temporary string buffer. Move the text to a safe place if you aren't using it quickly or if the length of the line is bigger than the size of a temporary string. ## Writing To A File To write a byte to a file, pass it and the file handle to `file:write`. $h @FID file:write $e @FID file:write $l @FID file:write $l @FID file:write $o @FID file:write Though cells are 32 or 64 bits in size, only the byte value will be written to the file. ## Deleting Files You can delete a file by passing the file name to `file:delete`. /tmp/test file:delete ## Check For File Existance Use `file:exists?` to detect the existance of a file. Pass it a file name and it will return `TRUE` if existing or `FALSE` if it does not. '/etc/motd file:exists? This will also return `TRUE` if the filename is a directory. ## Flush Caches Use `file:flush` to flush the system caches for a file. Pass a file handle to this. @FID file:flush ## Seek A Position Within A File You can use `file:seek` to move the internal file pointer for a given file. Pass this the new location and a file. #100 @FID file:seek The location for the file pointer is a fixed offset from the start of the file, not a relative offset. ## Get The Current Position Within A File To find the current value of the file pointer within a file just pass the file handle to `file:tell`. @FID file:tell This returns a number that is the number of bytes into the file that the file pointer is currently at. ## Determine The Size Of A File Use `file:size` to return the size of a file. Pass this a file handle and it will return the size of a file, or 0 if empty. If the file is a directory, it returns -1. @FID file:size ## Reading An Entire File If you want to read an entire file into memory you can use `file:slurp`. This takes the starting address of a memory region and the name of the file. here '/etc/motd file:slurp Take care that the memory buffer is large enough for the file being read or you will run into problems. ## Writing A String To A File If you have a string that you want to write to a file, replacing any existing contents, you can use `file:spew`. This takes the string to write and a file name. 'hello_world '/tmp/test.txt file:spew ## Iterating Over A File, Line By Line You can easily iterate over each line in a file using the word `file:for-each-line`. This will take a file name and a quote, read each line into a temporary string, then pass this string to the quote. '/etc/motd [ s:put nl ] file:for-each-line