A File.T
, or {\em file handle}, is a source and/or sink of bytes.
File handles provide an operating-system independent way to perform
raw I/O. For buffered I/O, use the FileRd
and FileWr
interfaces instead. A file handle is created using OpenFile
or
OpenFileReadonly
in the FS
interface.
\index{file!handle}
\index{unbuffered file I/O}
\index{file!unbuffered I/O}
\index{I/O!unbuffered}
INTERFACEFormally, a file handleFile ; IMPORT Atom, OSError, Time; TYPE T <: Public; Public = OBJECT METHODS read(VAR (*OUT*) b: ARRAY OF Byte; mayBlock: BOOLEAN := TRUE): INTEGER RAISES {OSError.E}; write(READONLY b: ARRAY OF Byte) RAISES {OSError.E}; status(): Status RAISES {OSError.E}; close() RAISES {OSError.E} END; Byte = BITS 8 FOR [0 .. 255]; Status = RECORD type: Type; modificationTime: Time.T; size: LONGCARD; END; Type = Atom.T; END File.
h
has the components:
type(h) an atom, the type of file readable(h) a boolean writable(h) a boolean src(h) (a REF to) a sequence of bytes srcCur(h) an integer in the range [0..len(src(h))] srcEof(h) a boolean snk(h) (a REF to) a sequence of bytes snkCur(h) an integer in the range [0..len(snk(h))]The
src...
components are meaningful only if readable(h)
. The
sequence src(h)
is zero-based: src(h)[i]
is valid for i
from
0
to len(src(h))-1
. For some subtypes of File.T
, the
sequence src(h)
can grow without bound.
The snk...
components are meaningful only if writable(h)
. The
sequence snk(h)
is zero based: snk(h)[i]
is valid for i
from
0
to len(snk(h))-1
.
For full details on the semantics of a file handle, consult the
interface defining the particular subtype, for example, Pipe.T
,
Terminal.T
, or RegularFile.T
. In the case where no exceptions
are raised, the methods of the subtypes of File.T
obey the
following specifications:
The call
h.read(b, mayBlock)is equivalent to
IF NOT readable(h) OR NUMBER(b) = 0 THEN Cause checked runtime error END; IF srcCur(h) = len(src(h)) AND NOT srcEof(h) THEN IF NOT mayBlock THEN RETURN -1 END; Block until srcCur(h) < len(src(h)) OR srcEof(h) END; IF srcCur(h) = len(src(h)) THEN RETURN 0 END; Choose k such that: 1 <= k <= MIN(NUMBER(b), len(src(h))-srcCur(h)); FOR i := 0 TO k-1 DO b[i] := src(h)[srcCur(h)]; INC(srcCur(h)) END; RETURN k\index{non-blocking read}
A result of zero always means end of file. The meaning of a
subsequent read after end of file has been reached is undefined for
a File.T
but may be defined for a particular subtype.
The call
h.write(b)is equivalent to
IF NOT writable(h) THEN Cause checked runtime error END; FOR i := 0 TO NUMBER(b)-1 DO IF snkCur(h) = len(snk(h)) THEN Extend snk(h) by one byte END; snk(h)[snkCur(h)] := b[i] INC(srcCur(h)) END;The
read
and write
methods are not alertable because it isn't
possible to alert a thread blocked in a Win32 ReadFile
or
WriteFile
system call.
The call
h.status()returns a result whose
type
field contains type(h)
. See the
documentation for each subtype of File.T
for more details,
including the values of the modificationTime
and size
fields of
the result, if any.
The call
h.close()is equivalent to
readable(h) := FALSE; writable(h) := FALSEAdditionally, it releases any subtype-specific resources used by
h
. Every file handle should be closed.
Clients should assume that file handles are unmonitored and should
avoid concurrent accesses to a file handle from multiple threads.
A particular subtype of File.T
may provide a stronger
specification with respect to atomicity.