Module std::io
I/O, including files, networking, timers, and processes
std::io
provides Rust's basic I/O types,
for reading and writing to files, TCP, UDP,
and other types of sockets and pipes,
manipulating the file system, spawning processes and signal handling.
Examples
Some examples of obvious things you might want to do
Read lines from stdin
use std::io; for line in io::stdin().lines() { print!("{}", line.unwrap()); }
Read a complete file
use std::io::File; let contents = File::open(&Path::new("message.txt")).read_to_end();
Write a line to a file
use std::io::File; let mut file = File::create(&Path::new("message.txt")); file.write(bytes!("hello, file!\n"));
Iterate over the lines of a file
use std::io::BufferedReader; use std::io::File; let path = Path::new("message.txt"); let mut file = BufferedReader::new(File::open(&path)); for line in file.lines() { print!("{}", line.unwrap()); }
Pull the lines of a file into a vector of strings
use std::io::BufferedReader; use std::io::File; let path = Path::new("message.txt"); let mut file = BufferedReader::new(File::open(&path)); let lines: ~[~str] = file.lines().map(|x| x.unwrap()).collect();
Make a simple TCP client connection and request
use std::io::net::ip::SocketAddr; use std::io::net::tcp::TcpStream; let addr = from_str::<SocketAddr>("127.0.0.1:8080").unwrap(); let mut socket = TcpStream::connect(addr).unwrap(); socket.write(bytes!("GET / HTTP/1.0\n\n")); let response = socket.read_to_end();
Make a simple TCP server
use std::io::net::tcp::TcpListener; use std::io::net::ip::{Ipv4Addr, SocketAddr}; use std::io::{Acceptor, Listener}; let addr = SocketAddr { ip: Ipv4Addr(127, 0, 0, 1), port: 80 }; let listener = TcpListener::bind(addr); // bind the listener to the specified address let mut acceptor = listener.listen(); // accept connections and process them for stream in acceptor.incoming() { spawn(proc() { handle_client(stream); }); } // close the socket server drop(acceptor);
Error Handling
I/O is an area where nearly every operation can result in unexpected errors. Errors should be painfully visible when they happen, and handling them should be easy to work with. It should be convenient to handle specific I/O errors, and it should also be convenient to not deal with I/O errors.
Rust's I/O employs a combination of techniques to reduce boilerplate while still providing feedback about errors. The basic strategy:
- All I/O operations return
IoResult<T>
which is equivalent toResult<T, IoError>
. TheResult
type is defined in thestd::result
module. - If the
Result
type goes unused, then the compiler will by default emit a warning about the unused result. This is becauseResult
has the#[must_use]
attribute. - Common traits are implemented for
IoResult
, e.g.impl<R: Reader> Reader for IoResult<R>
, so that error values do not have to be 'unwrapped' before use.
These features combine in the API to allow for expressions like
File::create(&Path::new("diary.txt")).write(bytes!("Met a girl.\n"))
without having to worry about whether "diary.txt" exists or whether
the write succeeds. As written, if either new
or write_line
encounters an error then the result of the entire expression will
be an error.
If you wanted to handle the error though you might write:
use std::io::File; match File::create(&Path::new("diary.txt")).write(bytes!("Met a girl.\n")) { Ok(()) => (), // succeeded Err(e) => println!("failed to write to my diary: {}", e), }
So what actually happens if create
encounters an error?
It's important to know that what new
returns is not a File
but an IoResult<File>
. If the file does not open, then new
will simply
return Err(..)
. Because there is an implementation of Writer
(the trait
required ultimately required for types to implement write_line
) there is no
need to inspect or unwrap the IoResult<File>
and we simply call write_line
on it. If new
returned an Err(..)
then the followup call to write_line
will also return an error.
try!
Explicit pattern matching on IoResult
s can get quite verbose, especially
when performing many I/O operations. Some examples (like those above) are
alleviated with extra methods implemented on IoResult
, but others have more
complex interdependencies among each I/O operation.
The try!
macro from std::macros
is provided as a method of early-return
inside Result
-returning functions. It expands to an early-return on Err
and otherwise unwraps the contained Ok
value.
If you wanted to read several u32
s from a file and return their product:
use std::io::{File, IoResult}; fn file_product(p: &Path) -> IoResult<u32> { let mut f = File::open(p); let x1 = try!(f.read_le_u32()); let x2 = try!(f.read_le_u32()); Ok(x1 * x2) } match file_product(&Path::new("numbers.bin")) { Ok(x) => println!("{}", x), Err(e) => println!("Failed to read numbers!") }
With try!
in file_product
, each read_le_u32
need not be directly
concerned with error handling; instead its caller is responsible for
responding to errors that may occur while attempting to read the numbers.
Reexports
pub use self::stdio::stdin; |
pub use self::stdio::stdout; |
pub use self::stdio::stderr; |
pub use self::stdio::print; |
pub use self::stdio::println; |
pub use self::fs::File; |
pub use self::timer::Timer; |
pub use self::net::ip::IpAddr; |
pub use self::net::tcp::TcpListener; |
pub use self::net::tcp::TcpStream; |
pub use self::net::udp::UdpStream; |
pub use self::pipe::PipeStream; |
pub use self::process::{Process, ProcessConfig}; |
Modules
extensions | Utility mixins that apply to all Readers and Writers |
fs | Synchronous File I/O |
net | Networking I/O |
pipe | Synchronous, in-memory pipes. |
process | Bindings for executing child processes |
signal | Signal handling |
stdio | Non-blocking access to stdin, stdout, and stderr. |
test | Various utility functions useful for writing I/O tests |
timer | Synchronous Timers |
util | Utility implementations of Reader and Writer |
Structs
BufReader | Reads from a fixed-size byte slice |
BufWriter | Writes to a fixed-size byte slice |
BufferedReader | Wraps a Reader and buffers input from it |
BufferedStream | Wraps a Stream and buffers input and output to and from it. |
BufferedWriter | Wraps a Writer and buffers output to it |
ChanReader | Allows reading from a rx. |
ChanWriter | Allows writing to a tx. |
Chars | An iterator that reads a utf8-encoded character on each iteration,
until |
FileStat | A structure used to describe metadata information about a file. This
structure is created through the |
IncomingConnections | An infinite iterator over incoming connection attempts.
Calling |
IoError | The type passed to I/O condition handlers to indicate error |
LineBufferedWriter | Wraps a Writer and buffers output to it, flushing whenever a newline ( |
Lines | An iterator that reads a line on each iteration,
until |
MemReader | Reads from an owned byte vector |
MemWriter | Writes to an owned, growable byte vector |
RefReader | A |
RefWriter | A |
TempDir | A wrapper for a path to temporary directory implementing automatic scope-based deletion. |
UnstableFileStat | This structure represents all of the possible information which can be
returned from a |
Enums
FileAccess | Access permissions with which the file should be opened. |
FileMode | A mode specifies how a file should be opened or created. These modes are
passed to |
FileType | Different kinds of files which can be identified by a call to stat |
IoErrorKind | A list specifying general categories of I/O error. |
SeekStyle | When seeking, the resulting cursor is offset from a base by the offset given
to the |
Statics
pub static AllPermissions: FilePermission = 0x1ff |
A mask for all possible permission bits |
pub static GroupExecute: FilePermission = 0x008 |
|
pub static GroupRWX: FilePermission = GroupRead | GroupWrite | GroupExecute |
|
pub static GroupRead: FilePermission = 0x020 |
|
pub static GroupWrite: FilePermission = 0x010 |
|
pub static OtherExecute: FilePermission = 0x001 |
|
pub static OtherRWX: FilePermission = OtherRead | OtherWrite | OtherExecute |
|
pub static OtherRead: FilePermission = 0x004 |
|
pub static OtherWrite: FilePermission = 0x002 |
|
pub static UserDir: FilePermission = UserRWX | GroupRead | GroupExecute | OtherRead | OtherExecute |
A set of permissions for user owned directories, this is equivalent to 0755 on unix-like systems. |
pub static UserExec: FilePermission = UserDir |
A set of permissions for user owned executables, this is equivalent to 0755 on unix-like systems. |
pub static UserExecute: FilePermission = 0x040 |
|
pub static UserFile: FilePermission = UserRead | UserWrite | GroupRead | OtherRead |
A set of permissions for user owned files, this is equivalent to 0644 on unix-like systems. |
pub static UserRWX: FilePermission = UserRead | UserWrite | UserExecute |
|
pub static UserRead: FilePermission = 0x100 |
|
pub static UserWrite: FilePermission = 0x080 |
Traits
Acceptor | An acceptor is a value that presents incoming connections |
Buffer | A Buffer is a type of reader which has some form of internal buffering to
allow certain kinds of reading operations to be more optimized than others.
This type extends the |
Listener | A listener is a value that can consume itself to start listening for connections. |
Reader | A trait for objects which are byte-oriented streams. Readers are defined by
one method, |
Seek | An object implementing |
Stream | A Stream is a readable and a writable object. Data written is typically received by the object which reads receive data from. |
Writer | A trait for objects which are byte-oriented streams. Writers are defined by
one method, |
Functions
standard_error | Creates a standard error for a commonly used flavor of error. The |
Type Definitions
FilePermission | A set of permissions for a file or directory is represented by a set of flags which are or'd together. |
IoResult | A convenient typedef of the return value of any I/O action. |