Expand description
Traits, helpers, and type definitions for core I/O functionality.
The std::io
module contains a number of common things you’ll need
when doing input and output. The most core part of this module is
the Read
and Write
traits, which provide the
most general interface for reading and writing input and output.
Read and Write
Because they are traits, Read
and Write
are implemented by a number
of other types, and you can implement them for your types too. As such,
you’ll see a few different types of I/O throughout the documentation in
this module: File
s, TcpStream
s, and sometimes even Vec<T>
s. For
example, Read
adds a read
method, which we can use on
File
s:
use std::io;
use std::io::prelude::*;
use std::fs::File;
fn main() -> io::Result<()> {
let mut f = File::open("foo.txt")?;
let mut buffer = [0; 10];
// read up to 10 bytes
let n = f.read(&mut buffer)?;
println!("The bytes: {:?}", &buffer[..n]);
Ok(())
}
RunRead
and Write
are so important, implementors of the two traits have a
nickname: readers and writers. So you’ll sometimes see ‘a reader’ instead
of ‘a type that implements the Read
trait’. Much easier!
Seek and BufRead
Beyond that, there are two important traits that are provided: Seek
and BufRead
. Both of these build on top of a reader to control
how the reading happens. Seek
lets you control where the next byte is
coming from:
use std::io;
use std::io::prelude::*;
use std::io::SeekFrom;
use std::fs::File;
fn main() -> io::Result<()> {
let mut f = File::open("foo.txt")?;
let mut buffer = [0; 10];
// skip to the last 10 bytes of the file
f.seek(SeekFrom::End(-10))?;
// read up to 10 bytes
let n = f.read(&mut buffer)?;
println!("The bytes: {:?}", &buffer[..n]);
Ok(())
}
RunBufRead
uses an internal buffer to provide a number of other ways to read, but
to show it off, we’ll need to talk about buffers in general. Keep reading!
BufReader and BufWriter
Byte-based interfaces are unwieldy and can be inefficient, as we’d need to be
making near-constant calls to the operating system. To help with this,
std::io
comes with two structs, BufReader
and BufWriter
, which wrap
readers and writers. The wrapper uses a buffer, reducing the number of
calls and providing nicer methods for accessing exactly what you want.
For example, BufReader
works with the BufRead
trait to add extra
methods to any reader:
use std::io;
use std::io::prelude::*;
use std::io::BufReader;
use std::fs::File;
fn main() -> io::Result<()> {
let f = File::open("foo.txt")?;
let mut reader = BufReader::new(f);
let mut buffer = String::new();
// read a line into buffer
reader.read_line(&mut buffer)?;
println!("{buffer}");
Ok(())
}
RunBufWriter
doesn’t add any new ways of writing; it just buffers every call
to write
:
use std::io;
use std::io::prelude::*;
use std::io::BufWriter;
use std::fs::File;
fn main() -> io::Result<()> {
let f = File::create("foo.txt")?;
{
let mut writer = BufWriter::new(f);
// write a byte to the buffer
writer.write(&[42])?;
} // the buffer is flushed once writer goes out of scope
Ok(())
}
RunStandard input and output
A very common source of input is standard input:
use std::io;
fn main() -> io::Result<()> {
let mut input = String::new();
io::stdin().read_line(&mut input)?;
println!("You typed: {}", input.trim());
Ok(())
}
RunNote that you cannot use the ?
operator in functions that do not return
a Result<T, E>
. Instead, you can call .unwrap()
or match
on the return value to catch any possible errors:
use std::io;
let mut input = String::new();
io::stdin().read_line(&mut input).unwrap();
RunAnd a very common source of output is standard output:
use std::io;
use std::io::prelude::*;
fn main() -> io::Result<()> {
io::stdout().write(&[42])?;
Ok(())
}
RunOf course, using io::stdout
directly is less common than something like
println!
.
Iterator types
A large number of the structures provided by std::io
are for various
ways of iterating over I/O. For example, Lines
is used to split over
lines:
use std::io;
use std::io::prelude::*;
use std::io::BufReader;
use std::fs::File;
fn main() -> io::Result<()> {
let f = File::open("foo.txt")?;
let reader = BufReader::new(f);
for line in reader.lines() {
println!("{}", line?);
}
Ok(())
}
RunFunctions
There are a number of functions that offer access to various features. For example, we can use three of these functions to copy everything from standard input to standard output:
use std::io;
fn main() -> io::Result<()> {
io::copy(&mut io::stdin(), &mut io::stdout())?;
Ok(())
}
Runio::Result
Last, but certainly not least, is io::Result
. This type is used
as the return type of many std::io
functions that can cause an error, and
can be returned from your own functions as well. Many of the examples in this
module use the ?
operator:
use std::io;
fn read_input() -> io::Result<()> {
let mut input = String::new();
io::stdin().read_line(&mut input)?;
println!("You typed: {}", input.trim());
Ok(())
}
RunThe return type of read_input()
, io::Result<()>
, is a very
common type for functions which don’t have a ‘real’ return value, but do want to
return errors if they happen. In this case, the only purpose of this function is
to read the line and print it, so we use ()
.
Platform-specific behavior
Many I/O functions throughout the standard library are documented to indicate what various library or syscalls they are delegated to. This is done to help applications both understand what’s happening under the hood as well as investigate any possibly unclear semantics. Note, however, that this is informative, not a binding contract. The implementation of many of these functions are subject to change over time and may call fewer or more syscalls/library functions.
Modules
The I/O Prelude.
Structs
A wrapper around a byte buffer that is incrementally filled and initialized.
The BufReader<R>
struct adds buffering to any reader.
Wraps a writer and buffers its output.
An iterator over u8
values of a reader.
Adapter to chain together two readers.
A reader which is always at EOF.
An error returned by BufWriter::into_inner
which combines an error that
happened while writing out the buffer, and the buffered writer object
which may be used to recover from the condition.
A buffer type used with Write::write_vectored
.
A buffer type used with Read::read_vectored
.
Wraps a writer and buffers output to it, flushing whenever a newline
(0x0a
, '\n'
) is detected.
An iterator over the lines of an instance of BufRead
.
A reader which yields one byte over and over and over and over and over and…
A writer which will move data into the void.
An iterator over the contents of an instance of BufRead
split on a
particular byte.
A handle to the standard error stream of a process.
A locked reference to the Stderr
handle.
A handle to the standard input stream of a process.
A handle to the global standard output stream of the current process.
A locked reference to the Stdout
handle.
Reader adapter which limits the bytes read from an underlying reader.
Error returned for the buffered data from BufWriter::into_parts
, when the underlying
writer has previously panicked. Contains the (possibly partly written) buffered data.
Enums
A list specifying general categories of I/O error.
Enumeration of possible methods to seek within an I/O object.
Traits
A BufRead
is a type of Read
er which has an internal buffer, allowing it
to perform extra ways of reading.
The Read
trait allows for reading bytes from a source.
The Seek
trait provides a cursor which can be moved within a stream of
bytes.
A trait for objects which are byte-oriented sinks.
Functions
Copies the entire contents of a reader into a writer.
Constructs a new handle to an empty reader.
Creates an instance of a reader that infinitely repeats one byte.
Creates an instance of a writer which will successfully consume all data.
Constructs a new handle to the standard error of the current process.
Constructs a new handle to the standard input of the current process.
Constructs a new handle to the standard output of the current process.