open System
open System.IO
// Reading files requires checking most operations for errors.
// This helper will streamline our error checks below.
let check ( result : Result < ' T , exn >) =
match result with
| Ok value -> value
| Error e -> raise e
[< EntryPoint >]
let main argv =
// Perhaps the most basic file reading task is
// slurping a file's entire contents into memory.
let dat =
File . ReadAllText ( "/tmp/dat" )
|> check
printfn "%s" dat
// You'll often want more control over how and what
// parts of a file are read. For these tasks, start
// by opening a file to obtain a FileStream.
use f = new FileStream ( "/tmp/dat" , FileMode . Open )
// Read some bytes from the beginning of the file.
// Allow up to 5 to be read but also note how many
// actually were read.
let b1 = Array . zeroCreate 5
let n1 = f . Read ( b1 , 0 , b1 . Length )
printfn "%d bytes: %s" n1 ( System . Text . Encoding . UTF8 . GetString ( b1 , 0 , n1 ))
// You can also seek to a known location in the file
// and read from there.
f . Seek ( 6L , SeekOrigin . Begin ) |> ignore
let b2 = Array . zeroCreate 2
let n2 = f . Read ( b2 , 0 , b2 . Length )
printfn "%d bytes @ %d: %s" n2 6 ( System . Text . Encoding . UTF8 . GetString ( b2 , 0 , n2 ))
// Other methods of seeking are relative to the
// current cursor position,
f . Seek ( 4L , SeekOrigin . Current ) |> ignore
// and relative to the end of the file.
f . Seek (- 10L , SeekOrigin . End ) |> ignore
// The FileStream provides some functions that may
// be helpful for file reading. For example, reads
// like the ones above can be more robustly
// implemented with ReadExactly.
f . Seek ( 6L , SeekOrigin . Begin ) |> ignore
let b3 = Array . zeroCreate 2
f . ReadExactly ( b3 , 0 , b3 . Length )
printfn "%d bytes @ %d: %s" b3 . Length 6 ( System . Text . Encoding . UTF8 . GetString ( b3 ))
// There is no built-in rewind, but
// Seek(0, SeekOrigin.Begin) accomplishes this.
f . Seek ( 0L , SeekOrigin . Begin ) |> ignore
// The StreamReader class implements a buffered
// reader that may be useful both for its efficiency
// with many small reads and because of the additional
// reading methods it provides.
use r4 = new StreamReader ( f )
let b4 = r4 . ReadLine ()
printfn "5 bytes: %s" ( b4 . Substring ( 0 , 5 ))
// The 'use' keyword ensures that the file is closed
// when we're done (it's equivalent to 'using' in C#)
0 // return an integer exit code