8.1 Varieties of Ports
Various functions create various kinds of ports. Here are a few examples:
Files: The open-output-file function opens a file for writing, and open-input-file opens a file for reading.
Examples:> (define out (open-output-file "data")) > (display "hello" out) > (close-output-port out) > (define in (open-input-file "data")) > (read-line in) "hello"
> (close-input-port in) If a file exists already, then open-output-file raises an exception by default. Supply an option like #:exists 'truncate or #:exists 'update to re-write or update the file:
Examples:> (define out (open-output-file "data" #:exists 'truncate)) > (display "howdy" out) > (close-output-port out) Instead of having to match the open calls with close calls, most Racket programmers will use the call-with-input-file and call-with-output-file functions which take a function to call to carry out the desired operation. This function gets as its only argument the port, which is automatically opened and closed for the operation.
Examples:> (call-with-output-file "data" #:exists 'truncate (lambda (out) (display "hello" out))) > (call-with-input-file "data" (lambda (in) (read-line in))) "hello"
Strings: The open-output-string function creates a port that accumulates data into a string, and get-output-string extracts the accumulated string. The open-input-string function creates a port to read from a string.
Examples:> (define p (open-output-string)) > (display "hello" p) > (get-output-string p) "hello"
> (read-line (open-input-string "goodbye\nfarewell")) "goodbye"
TCP Connections: The tcp-connect function creates both an input port and an output port for the client side of a TCP communication. The tcp-listen function creates a server, which accepts connections via tcp-accept.
Examples:> (define server (tcp-listen 12345)) > (define-values (c-in c-out) (tcp-connect "localhost" 12345)) > (define-values (s-in s-out) (tcp-accept server)) > (display "hello\n" c-out) > (close-output-port c-out) > (read-line s-in) "hello"
> (read-line s-in) #<eof>
Process Pipes: The subprocess function runs a new process at the OS level and returns ports that correspond to the subprocess’s stdin, stdout, and stderr. (The first three arguments can be certain kinds of existing ports to connect directly to the subprocess, instead of creating new ports.)
Examples:> (define-values (p stdout stdin stderr) (subprocess #f #f #f "/usr/bin/wc" "-w")) > (display "a b c\n" stdin) > (close-output-port stdin) > (read-line stdout) " 3"
> (close-input-port stdout) > (close-input-port stderr) Internal Pipes: The make-pipe function returns two ports that are ends of a pipe. This kind of pipe is internal to Racket, and not related to OS-level pipes for communicating between different processes.
Examples:> (define-values (in out) (make-pipe)) > (display "garbage" out) > (close-output-port out) > (read-line in) "garbage"