114 lines
5.4 KiB
Racket
114 lines
5.4 KiB
Racket
#lang scribble/doc
|
|
@(require "mz.ss")
|
|
|
|
@title[#:tag "port-buffers"]{Port Buffers and Positions}
|
|
|
|
Some ports---especially those that read from and write to files---are
|
|
internally buffered:
|
|
|
|
@itemize{
|
|
|
|
@item{An input port is typically block buffered by default, which
|
|
means that on any read, the buffer is filled with
|
|
immediately-available bytes to speed up future reads. Thus, if
|
|
a file is modified between a pair of reads to the file, the
|
|
second read can produce stale data. Calling
|
|
@scheme[file-position] to set an input port's file position
|
|
flushes its buffer.}
|
|
|
|
@item{And output port is typically block buffered by default, though
|
|
a terminal output port is line buffered, and the initial error
|
|
output port is unbuffered. An output buffer is filled with a
|
|
sequence of written bytes to be committed as a group, either
|
|
when the buffer is full (in block mode), when a newline is
|
|
written (in line mode), when the port is closed via
|
|
@scheme[close-output-port], or when a flush is explicitly
|
|
requested via a procedure like @scheme[flush-output].}
|
|
|
|
}
|
|
|
|
If a port supports buffering, its buffer mode can be changed via
|
|
@scheme[file-stream-buffer-mode] (even if the port is not a
|
|
@tech{file-stream port}).
|
|
|
|
For an input port, peeking always places peeked bytes into the port's
|
|
buffer, even when the port's buffer mode is @scheme['none];
|
|
furthermore, on some platforms, testing the port for input (via
|
|
@scheme[char-ready?] or @scheme[sync]) may be implemented with a
|
|
peek. If an input port's buffer mode is @scheme['none], then at most
|
|
one byte is read for @scheme[read-bytes-avail!*],
|
|
@scheme[read-bytes-avail!], @scheme[peek-bytes-avail!*], or
|
|
@scheme[peek-bytes-avail!]; if any bytes are buffered in the port
|
|
(e.g., to satisfy a previous peek), the procedures may access multiple
|
|
buffered bytes, but no further bytes are read.
|
|
|
|
In addition, the initial current output and error ports are
|
|
automatically flushed when @scheme[read], @scheme[read-line],
|
|
@scheme[read-bytes], @scheme[read-string], etc. are performed on the
|
|
initial standard input port; more precisely, flushing is performed by
|
|
the default port read handler (see @scheme[port-read-handler]).
|
|
|
|
@defproc[(flush-output [out output-port? (current-output-port)]) void?]{
|
|
|
|
@index['("ports" "flushing")]{Forces} all buffered data in the given
|
|
output port to be physically written. Only @tech{file-stream ports},
|
|
TCP ports, and custom ports (see @secref["customport"]) use
|
|
buffers; when called on a port without a buffer, @scheme[flush-output]
|
|
has no effect.}
|
|
|
|
@defproc*[([(file-stream-buffer-mode [port port?]) (one-of/c 'none 'line 'block #f)]
|
|
[(file-stream-buffer-mode [port port?][mode (one-of/c 'none 'line 'block)]) void?])]{
|
|
|
|
Gets or sets the buffer mode for @scheme[port], if
|
|
possible. @tech{File-stream ports} support setting the buffer mode,
|
|
TCP ports (see @secref["networking"]) support setting and getting
|
|
the buffer mode, and custom ports (see @secref["customport"]) may
|
|
support getting and setting buffer modes.
|
|
|
|
If @scheme[mode] is provided, it must be one of
|
|
@indexed-scheme['none], @indexed-scheme['line] (output only), or
|
|
@indexed-scheme['block], and the port's buffering is set
|
|
accordingly. If the port does not support setting the mode, the
|
|
@exnraise[exn:fail].
|
|
|
|
If @scheme[mode] is not provided, the current mode is returned, or
|
|
@scheme[#f] is returned if the mode cannot be determined. If
|
|
@scheme[file-stream-port] is an input port and @scheme[mode] is
|
|
@scheme['line], the @exnraise[exn:fail:contract].}
|
|
|
|
@defproc*[([(file-position [port port?]) nonnegative-exact-integer?]
|
|
[(file-position [port port?] [pos (or/c nonnegative-exact-integer? eof-object?)]) void?])]{
|
|
|
|
Returns or sets the current read/write position of @scheme[port].
|
|
|
|
Calling @scheme[file-position] without a position on a
|
|
non-file/non-string input port returns the number of bytes that have
|
|
been read from that port if the position is known (see
|
|
@secref["linecol"]), otherwise the @exnraise[exn:fail:filesystem].
|
|
|
|
For @tech{file-stream ports} and string ports, the position-setting
|
|
variants sets the read/write position to @scheme[pos] relative to the
|
|
beginning of the file/string if @scheme[pos] is a number, or to the
|
|
current end of the file/string if @scheme[pos] is @scheme[eof]. In
|
|
position-setting mode, @scheme[file-position] raises the
|
|
@scheme[exn:fail:contract] exception for port kinds other than
|
|
file-stream and string ports. Furthermore, not all @tech{file-stream
|
|
ports} support setting the position; f @scheme[file-position] is
|
|
called with a position argument on such a @tech{file-stream port}, the
|
|
@exnraise[exn:fail:filesystem].
|
|
|
|
When @scheme[file-position] sets the position @scheme[pos] beyond the
|
|
current size of an output file or string, the file/string is enlarged
|
|
to size @scheme[pos] and the new region is filled with @scheme[0]
|
|
bytes. If @scheme[pos] is beyond the end of an input file or string,
|
|
then reading thereafter returns @scheme[eof] without changing the
|
|
port's position.
|
|
|
|
When changing the file position for an output port, the port is first
|
|
flushed if its buffer is not empty. Similarly, setting the position
|
|
for an input port clears the port's buffer (even if the new position
|
|
is the same as the old position). However, although input and output
|
|
ports produced by @scheme[open-input-output-file] share the file
|
|
position, setting the position via one port does not flush the other
|
|
port's buffer.}
|