15 April 2016

Lesson 17 – Using files in 8th – Part 2


Reading a file in one sweep

Sometimes it is useful to read a file into memory in one go. For that we have the word f:slurp.
This word creates a buffer instead of a string! This means that is not the best way for reading a text file, if only because it can consume lots of memory. For a text file we’d better use f:eachline as in this example:



OS level file write operations invoked by 8th


f:chmod
Most often used to change the read-only mode of the file; on Unix-like OSes can do many more things.

f:copy
Tries to copy a file.

f:copydir
Tries to (recursively) copy a whole directory.

f:link
Tries to create a symbolic link to a file. This feature is mostly used in Unix like OS-es.

f:mkdir
Tries to create a new directory.

OS level file info requests

f:canwrite?
Detects if it is possible to write to a given file.

f:ctime
Gets creation time of a file.

Read the manual

When I go through the manual for the f namespace I see a lot of very useful words.
So really, you should study the manual, otherwise you’ll miss the juicy parts of 8th

A final example of file handling

We will:
1. Go into the root directory c:\ (Windows here)
2. Check if a directory with the name example already exists there
3. If not, create it
4. Go into that directory
5. Create a small text file there
6. Query some file info of that file

Program source code


"example"  var, dirName
"test.txt" var, fileName
false      var, dirExists
["line 1\n", "line 2\n", "line 3\n"] var, records

: chkSubdir
  dirName @ f:exists?
  if 
    "The name already exists and ..." . cr
    dirName @ f:dir?
    if 
      true dirExists !
      "... it is indeed a directory!" . cr
    else
      "Error: a file with that name exists already!"
      . cr reset bye
    then
  else
    "The directory does not exist yet ..." . cr
  then
  ;

: makeDir
  dirExists @ not
  if
    "... so we create it now!" . cr
    dirName @ f:mkdir not
    if 
      "Error: cannot create directory!" . 
      cr reset bye 
    then
  then
  ;

: openFile
  fileName @ f:create dup   \ dup to retain file handle
  null? 
  if 
    "Error: error while creating file!" . 
    cr reset bye 
  then
  ;

: helpWrite
          \ Stack: file ix value   
  swap    \ Stack: file value ix
  drop    \ Stack: file value
  f:write \ Stack: file rc
  null? if "Error: writing to file!" . cr reset bye then
          \ Stack: file
  ;
  
: writeFile
  records @ ' helpWrite a:each 
  drop \ Get rid of array now
  ;

: openro
  fileName @ f:open-ro
  dup null? \ dup to retain file handle
  if
    "Error: error while reopening file!" . cr reset bye
  then
  ;
  
: queryFile
  getcwd "Current directory is: " . . cr
  fileName @ f:exists?
  if
    "The file does indeed exist now!" . cr
  else
    "Error: file not found!" . cr reset bye
  then
  openro
  f:size  "File size       : " . . " bytes" . cr
  f:ctime "File created at : " . . cr
  f:mtime "File modified at: " . . cr
  f:close
  ;
  
: app:main
  "c:\\" chdir     \ Set current directory to c:\
  chkSubdir        \ Does the subdirectory exist?
  makeDir          \ If not, create it!
  dirName @ chdir  \ Set current directory 
  openFile         \ Open a file for output
  writeFile        \ Write the records to the file
  f:close          \ Close the output file
  openro           \ Open written file for read
  queryFile        \ Now query some file specs
  bye
  ;
  

Below the output of two consecutive runs:



More info about 8th


8th Website:   http://8th-dev.com
8th Forum:   http://8th-dev.com/forum
My YouTube Channel:   https://goo.gl/DscYVD
The Big 8th Lessons Book:   http://goo.gl/qDa6fH