All input and output in Racket goes through ports. An input port supplies bytes (and, through UTF-8, characters); an output port takes them. A port may be a file, a string, a pipe, a network connection, a subprocess, or one that a program defines. The three current ports are parameters: (current-input-port), (current-output-port) and (current-error-port), and most functions take an optional port argument that defaults to one of them.
Printing
| Function | Writes |
|---|---|
(display v [out]), (displayln v [out]) | the value for people: a string without quotes, a character as itself. displayln adds a newline |
(write v [out]), (writeln v [out]) | the value as read would read it back: strings in quotes, symbols with bars if needed |
(print v [out]), (println v [out]) | the value as an expression one would type to make it (a list is written '(1 2)); this is how the REPL shows results |
(write-string s [out]), (write-char c [out]), (write-bytes b [out]), (write-byte n [out]), (newline [out]) | raw text and bytes |
(printf fmt v …), (fprintf out fmt v …), (eprintf fmt v …), (format fmt v …) | formatted output; format returns a string. eprintf writes to the error port |
(pretty-print v), (pretty-write v), (pretty-display v), (pretty-format v) (racket/pretty) | wrap long values over lines; pretty-print-columns sets the width |
(~a v …), (~s v …), (~v v …), (~r n …), (~e …) (racket/format) | make strings: ~a like display, ~s like write, ~v like print, with #:width, #:align, #:pad-string, #:max-width and #:min-width; ~r formats numbers (#:precision, #:base, #:notation) |
(display-lines lst), (write-json js), (write-to-file v path), (display-to-file v path) | one line per element; JSON; a value to a file |
Format directives
| Directive | Prints the next argument |
|---|---|
~a ~A | with display |
~s ~S | with write |
~v ~V | with print |
~.a ~.s ~.v (and upper case) | like those, cut to (error-print-width) characters, ending ... if cut |
~e ~E | with the error value conversion handler and the error print width |
~c ~C | as a character, with write-char; the argument must be a character |
~b ~B, ~o ~O, ~x ~X | an exact number in binary, octal or hexadecimal |
~n, ~% | a newline (no argument) |
~~ | a tilde |
~ then white space | nothing: skips the white space that follows, up to a second line break |
A ~ followed by anything else, too few arguments, or too many arguments raises exn:fail:contract.
Reading
| Function | Reads |
|---|---|
(read-char [in]), (peek-char [in]), (read-byte [in]), (peek-byte [in]) | one character or byte, or eof; peek- does not consume it |
(read-line [in mode]) | a line without its end. The mode names the separator: 'linefeed (default), 'return, 'return-linefeed, 'any (any of the three, a return followed by a linefeed counting as one) and 'any-one (a return or a linefeed, without treating the pair as one); read-bytes-line does the same for bytes |
(read-string n [in]), (read-bytes n [in]), (read-string! …), (read-bytes! …), (read-bytes-avail! …) | up to a count, or into a buffer; peek-string and relatives look ahead |
(read [in]), (read-syntax [src in]) | one datum, using the reader (see Lexical structure), or eof; the second wraps it as a syntax object with locations |
(port->string in), (port->bytes in), (port->lines in), (port->list read in), (file->string path), (file->lines path), (file->value path) (racket/port, racket/file) | everything at once |
(byte-ready? [in]), (char-ready? [in]), (eof-object? v) | whether input is available without blocking; test for end of file |
(read-json in) (json) | a JSON value as a jsexpr |
Files
| Function | Does |
|---|---|
(open-input-file path #:mode) | opens a file for reading; the mode is 'binary (the default) or 'text, which on Windows turns return-linefeed into linefeed |
(open-output-file path #:mode #:exists #:permissions) | opens for writing. #:exists says what to do when the file exists: 'error (default), 'replace, 'truncate, 'must-truncate, 'truncate/replace, 'update, 'can-update or 'append |
(call-with-input-file path proc), (call-with-output-file path proc #:exists …), and the …file* versions | open, call a procedure with the port, close, return the result. The * forms close the port even on an error exit |
(with-input-from-file path thunk), (with-output-to-file path thunk #:exists …) | rebind the current port for the extent of a thunk |
(close-input-port p), (close-output-port p), (flush-output [out]) | close, and flush buffered output. A file port is flushed on exit by the plumber; close it anyway |
(file-position p [pos]), (file-size path), (file-exists? path), (directory-exists? path), (delete-file path), (rename-file-or-directory a b), (copy-file a b), (make-directory path), (directory-list path), (make-temporary-file), (file-or-directory-modify-seconds path) | file system access |
(port-try-file-lock? p mode), (port-file-unlock p), (port-file-identity p), (port-file-stat p) | advisory locks and file facts for file-stream ports |
#lang racket
(call-with-output-file "numbers.txt" #:exists 'replace
(lambda (out)
(for ([i (in-range 3)])
(fprintf out "line ~a\n" i))))
(call-with-input-file "numbers.txt"
(lambda (in)
(for/list ([line (in-lines in)]) (string-upcase line))))
(file->lines "numbers.txt") ; '("line 0" "line 1" "line 2")
(with-output-to-string (lambda () (display "hi"))) ; "hi"
(define-values (in out) (make-pipe))
(write 'data out)
(read in) ; 'data
Other ports
- String and byte ports.
(open-input-string s),(open-input-bytes b),(open-output-string)and(open-output-bytes), withget-output-stringandget-output-bytesto take the result.with-output-to-string,call-with-output-stringandwith-input-from-string(racket/port) wrap them. - Pipes.
(make-pipe)returns an input and an output port joined together. - Network.
tcp-listen,tcp-accept,tcp-connect,udp-open-socketand the others inracket/tcpandracket/udp; the ports they return are used like any other. - Processes.
subprocess,system,process,system*andfind-executable-path(racket/system) start programs and give their standard ports. - Custom ports.
make-input-portandmake-output-port(racket/port) andprop:input-port/prop:output-portmake ports from procedures;copy-port,input-port-append,make-limited-input-portandreencode-input-portcombine and convert them. - Events. A port is an event that is ready when input can be read or output written, so
syncandsync/timeoutwait on several; see Concurrency.
Characters, bytes and encodings
A port is a stream of bytes. A function that reads or writes characters converts them with UTF-8: a character read is one decoded from one to four bytes, and bytes that are not valid UTF-8 read as the replacement character U+FFFD. (bytes->string/utf-8 b), (string->bytes/utf-8 s), bytes->string/latin-1 and bytes->string/locale convert whole strings; bytes-open-converter and bytes-convert convert between named encodings (through iconv); reencode-input-port and reencode-output-port do it for ports. Line endings are the program's business: 'text mode on Windows converts them, and read-line chooses the separator. Racket writes \n as a single linefeed byte.
Paths
A path is not a string. (build-path "a" "b" "c.txt"), (string->path s), (path->string p), (path-element? v), (split-path p), (simplify-path p), (path->complete-path p), (path-replace-extension p ".bak"), (path-get-extension p), (file-name-from-path p) (racket/path), (current-directory), (find-system-path 'home-dir) and (system-type) are the main tools; path-string? accepts a string that is a valid path. (build-path/convention-type 'windows …) builds paths for another system.
Not described
Known, not yet covered
- Reference: the printer's parameters (
print-graph,print-struct,print-hash-table,print-boolean-long-formand the rest) andcurrent-print, custom write (prop:custom-write), the port layer (custom ports in detail, port buffers, line and column counting,port-count-lines!), the details of encodings and converters, byte and character locations, subprocess control and TCP/UDP functions were not described. The Reference chapters on I/O were read in part (file ports, string input, write and format directives, string ports). - Reference: the claim that bytes that are not valid UTF-8 read as
U+FFFDis from memory of the Reference; the section on encodings (ports.scrbl) was downloaded and not read. - Reference: the functions in the tables for
racket/port,racket/fileandracket/systemare named without the full argument lists.
See also
- Strings and regexps – regular expressions work on ports as well as strings
- Lexical structure – what
readaccepts - Scheme: I/O ports – the Scheme view of ports