Trait Read
trait Read
The Read trait allows for reading bytes from a source.
Implementors of the Read trait are called 'readers'.
Readers are defined by one required method, read(). Each call to read()
will attempt to pull bytes from this source into a provided buffer. A
number of other methods are implemented in terms of read(), giving
implementors a number of ways to read bytes while only needing to implement
a single method.
Readers are intended to be composable with one another. Many implementors
throughout std::io take and provide types which implement the Read
trait.
Please note that each call to read() may involve a system call, and
therefore, using something that implements BufRead, such as
BufReader, will be more efficient.
Repeated calls to the reader use the same cursor, so for example
calling read_to_end twice on a File will only return the file's
contents once. It's recommended to first call rewind() in that case.
Examples
Files implement Read:
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
f.read(&mut buffer)?;
let mut buffer = Vec::new();
// read the whole file
f.read_to_end(&mut buffer)?;
// read into a String, so that you don't need to do the conversion.
let mut buffer = String::new();
f.read_to_string(&mut buffer)?;
// and more! See the other methods for more details.
Ok(())
}
Read from &str because [&[u8]][prim@slice] implements Read:
# use std::io;
use std::io::prelude::*;
fn main() -> io::Result<()> {
let mut b = "This string will be read".as_bytes();
let mut buffer = [0; 10];
// read up to 10 bytes
b.read(&mut buffer)?;
// etc... it works exactly as a File does!
Ok(())
}
Required Methods
fn read(self: &mut Self, buf: &mut [u8]) -> Result<usize>Pull some bytes from this source into the specified buffer, returning how many bytes were read.
This function does not provide any guarantees about whether it blocks waiting for data, but if an object needs to block for a read and cannot, it will typically signal this via an
Errreturn value.If the return value of this method is
Ok(n), then implementations must guarantee that0 <= n <= buf.len(). A nonzeronvalue indicates that the bufferbufhas been filled in withnbytes of data from this source. Ifnis0, then it can indicate one of two scenarios:- This reader has reached its "end of file" and will likely no longer
be able to produce bytes. Note that this does not mean that the
reader will always no longer be able to produce bytes. As an example,
on Linux, this method will call the
recvsyscall for aTcpStream, where returning zero indicates the connection was shut down correctly. While forFile, it is possible to reach the end of file and get zero as result, but if more data is appended to the file, future calls toreadwill return more data. - The buffer specified was 0 bytes in length.
It is not an error if the returned value
nis smaller than the buffer size, even when the reader is not at the end of the stream yet. This may happen for example because fewer bytes are actually available right now (e. g. being close to end-of-file) or because read() was interrupted by a signal.As this trait is safe to implement, callers in unsafe code cannot rely on
n <= buf.len()for safety. Extra care needs to be taken whenunsafefunctions are used to access the read bytes. Callers have to ensure that no unchecked out-of-bounds accesses are possible even ifn > buf.len().Implementations of this method can make no assumptions about the contents of
bufwhen this function is called. It is recommended that implementations only write data tobufinstead of reading its contents.Correspondingly, however, callers of this method in unsafe code must not assume any guarantees about how the implementation uses
buf. The trait is safe to implement, so it is possible that the code that's supposed to write to the buffer might also read from it. It is your responsibility to make sure thatbufis initialized before callingread. Callingreadwith an uninitializedbuf(of the kind one obtains viaMaybeUninit<T>) is not safe, and can lead to undefined behavior.Errors
If this function encounters any form of I/O or other error, an error variant will be returned. If an error is returned then it must be guaranteed that no bytes were read.
An error of the
ErrorKind::Interruptedkind is non-fatal and the read operation should be retried if there is nothing else to do.Examples
Files implementRead: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(()) }- This reader has reached its "end of file" and will likely no longer
be able to produce bytes. Note that this does not mean that the
reader will always no longer be able to produce bytes. As an example,
on Linux, this method will call the
Provided Methods
fn read_vectored(self: &mut Self, bufs: &mut [IoSliceMut<'_>]) -> Result<usize>Like
read, except that it reads into a slice of buffers.Data is copied to fill each buffer in order, with the final buffer written to possibly being only partially filled. This method must behave equivalently to a single call to
readwith concatenated buffers.The default implementation calls
readwith either the first nonempty buffer provided, or an empty one if none exists.fn is_read_vectored(self: &Self) -> boolDetermines if this
Reader has an efficientread_vectoredimplementation.If a
Reader does not override the defaultread_vectoredimplementation, code using it may want to avoid the method all together and coalesce writes into a single buffer for higher performance.The default implementation returns
false.fn read_to_end(self: &mut Self, buf: &mut Vec<u8>) -> Result<usize>Reads all bytes until EOF in this source, placing them into
buf.All bytes read from this source will be appended to the specified buffer
buf. This function will continuously callread()to append more data tobufuntilread()returns eitherOk(0)or an error of non-ErrorKind::Interruptedkind.If successful, this function will return the total number of bytes read.
Errors
If this function encounters an error of the kind
ErrorKind::Interruptedthen the error is ignored and the operation will continue.If any other read error is encountered then this function immediately returns. Any bytes which have already been read will be appended to
buf.Examples
Files implementRead: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 = Vec::new(); // read the whole file f.read_to_end(&mut buffer)?; Ok(()) }(See also the
std::fs::readconvenience function for reading from a file.)Implementing
read_to_endWhen implementing the
io::Readtrait, it is recommended to allocate memory usingVec::try_reserve. However, this behavior is not guaranteed by all implementations, andread_to_endmay not handle out-of-memory situations gracefully.# use std::io::{self, BufRead}; # struct Example { example_datasource: io::Empty } impl Example { # fn get_some_data_for_the_example(&self) -> &'static [u8] { &[] } fn read_to_end(&mut self, dest_vec: &mut Vec<u8>) -> io::Result<usize> { let initial_vec_len = dest_vec.len(); loop { let src_buf = self.example_datasource.fill_buf()?; if src_buf.is_empty() { break; } dest_vec.try_reserve(src_buf.len())?; dest_vec.extend_from_slice(src_buf); // Any irreversible side effects should happen after `try_reserve` succeeds, // to avoid losing data on allocation error. let read = src_buf.len(); self.example_datasource.consume(read); } Ok(dest_vec.len() - initial_vec_len) } # }Usage Notes
read_to_endattempts to read a source until EOF, but many sources are continuous streams that do not send EOF. In these cases,read_to_endwill block indefinitely. Standard input is one such stream which may be finite if piped, but is typically continuous. For example,cat file | my-rust-programwill correctly terminate with anEOFupon closure of cat. Reading user input or running programs that remain open indefinitely will never terminate the stream withEOF(e.g.yes | my-rust-program).Using
.lines()with aBufReaderor usingreadcan provide a better solutionfn read_to_string(self: &mut Self, buf: &mut String) -> Result<usize>Reads all bytes until EOF in this source, appending them to
buf.If successful, this function returns the number of bytes which were read and appended to
buf.Errors
If the data in this stream is not valid UTF-8 then an error is returned and
bufis unchanged.See
read_to_endfor other error semantics.Examples
Files implementRead: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 = String::new(); f.read_to_string(&mut buffer)?; Ok(()) }(See also the
std::fs::read_to_stringconvenience function for reading from a file.)Usage Notes
read_to_stringattempts to read a source until EOF, but many sources are continuous streams that do not send EOF. In these cases,read_to_stringwill block indefinitely. Standard input is one such stream which may be finite if piped, but is typically continuous. For example,cat file | my-rust-programwill correctly terminate with anEOFupon closure of cat. Reading user input or running programs that remain open indefinitely will never terminate the stream withEOF(e.g.yes | my-rust-program).Using
.lines()with aBufReaderor usingreadcan provide a better solutionfn read_exact(self: &mut Self, buf: &mut [u8]) -> Result<()>Reads the exact number of bytes required to fill
buf.This function reads as many bytes as necessary to completely fill the specified buffer
buf.Implementations of this method can make no assumptions about the contents of
bufwhen this function is called. It is recommended that implementations only write data tobufinstead of reading its contents. The documentation onreadhas a more detailed explanation of this subject.Errors
If this function encounters an error of the kind
ErrorKind::Interruptedthen the error is ignored and the operation will continue.If this function encounters an "end of file" before completely filling the buffer, it returns an error of the kind
ErrorKind::UnexpectedEof. The contents ofbufare unspecified in this case.If any other read error is encountered then this function immediately returns. The contents of
bufare unspecified in this case.If this function returns an error, it is unspecified how many bytes it has read, but it will never read more than would be necessary to completely fill the buffer.
Examples
Files implementRead: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 exactly 10 bytes f.read_exact(&mut buffer)?; Ok(()) }fn read_buf(self: &mut Self, buf: BorrowedCursor<'_>) -> Result<()>Pull some bytes from this source into the specified buffer.
This is equivalent to the
readmethod, except that it is passed aBorrowedCursorrather than[u8]to allow use with uninitialized buffers. The new data will be appended to any existing contents ofbuf.The default implementation delegates to
read.This method makes it possible to return both data and an error but it is advised against.
fn read_buf_exact(self: &mut Self, cursor: BorrowedCursor<'_>) -> Result<()>Reads the exact number of bytes required to fill
cursor.This is similar to the
read_exactmethod, except that it is passed aBorrowedCursorrather than[u8]to allow use with uninitialized buffers.Errors
If this function encounters an error of the kind
ErrorKind::Interruptedthen the error is ignored and the operation will continue.If this function encounters an "end of file" before completely filling the buffer, it returns an error of the kind
ErrorKind::UnexpectedEof.If any other read error is encountered then this function immediately returns.
If this function returns an error, all bytes read will be appended to
cursor.fn by_ref(self: &mut Self) -> &mut Self where Self: SizedCreates a "by reference" adapter for this instance of
Read.The returned adapter also implements
Readand will simply borrow this current reader.Examples
Files implementRead:use std::io; use std::io::Read; use std::fs::File; fn main() -> io::Result<()> { let mut f = File::open("foo.txt")?; let mut buffer = Vec::new(); let mut other_buffer = Vec::new(); { let reference = f.by_ref(); // read at most 5 bytes reference.take(5).read_to_end(&mut buffer)?; } // drop our &mut reference so we can use f again // original file still usable, read the rest f.read_to_end(&mut other_buffer)?; Ok(()) }fn bytes(self: Self) -> Bytes<Self> where Self: SizedTransforms this
Readinstance to anIteratorover its bytes.The returned type implements
Iteratorwhere theItemisResult<[u8], io::Error>. The yielded item isOkif a byte was successfully read andErrotherwise. EOF is mapped to returningNonefrom this iterator.The default implementation calls
readfor each byte, which can be very inefficient for data that's not in memory, such asFile. Consider using aBufReaderin such cases.Examples
Files implementRead:use std::io; use std::io::prelude::*; use std::io::BufReader; use std::fs::File; fn main() -> io::Result<()> { let f = BufReader::new(File::open("foo.txt")?); for byte in f.bytes() { println!("{}", byte?); } Ok(()) }fn chain<R: Read>(self: Self, next: R) -> Chain<Self, R> where Self: SizedCreates an adapter which will chain this stream with another.
The returned
Readinstance will first read all bytes from this object until EOF is encountered. Afterwards the output is equivalent to the output ofnext.Examples
Files implementRead:use std::io; use std::io::prelude::*; use std::fs::File; fn main() -> io::Result<()> { let f1 = File::open("foo.txt")?; let f2 = File::open("bar.txt")?; let mut handle = f1.chain(f2); let mut buffer = String::new(); // read the value into a String. We could use any Read method here, // this is just one example. handle.read_to_string(&mut buffer)?; Ok(()) }fn take(self: Self, limit: u64) -> Take<Self> where Self: SizedCreates an adapter which will read at most
limitbytes from it.This function returns a new instance of
Readwhich will read at mostlimitbytes, after which it will always return EOF (Ok(0)). Any read errors will not count towards the number of bytes read and future calls toread()may succeed.Examples
Files implementRead:use std::io; use std::io::prelude::*; use std::fs::File; fn main() -> io::Result<()> { let f = File::open("foo.txt")?; let mut buffer = [0; 5]; // read at most five bytes let mut handle = f.take(5); handle.read(&mut buffer)?; Ok(()) }fn read_array<N: usize>(self: &mut Self) -> Result<[u8; N]> where Self: SizedRead and return a fixed array of bytes from this source.
This function uses an array sized based on a const generic size known at compile time. You can specify the size with turbofish (
reader.read_array::<8>()), or let type inference determine the number of bytes needed based on how the return value gets used. For instance, this function works well with functions likeu64::from_le_bytesto turn an array of bytes into an integer of the same size.Like
read_exact, if this function encounters an "end of file" before reading the desired number of bytes, it returns an error of the kindErrorKind::UnexpectedEof.use Cursor; use *;
Implementors
impl Read for TcpStreamimpl Read for UnixStreamimpl Read for &Stdinimpl<A: Allocator> Read for crate::collections::VecDeque<u8, A>impl Read for &Fileimpl<T> Read for Cursor<T>impl<R: Read + ?Sized> Read for &mut Rimpl Read for Repeatimpl Read for Stdinimpl Read for Fileimpl Read for crate::sync::Arc<File>impl Read for StdinLock<'_>impl Read for &TcpStreamimpl Read for Emptyimpl Read for ChildStdoutimpl Read for &[u8]impl Read for PipeReaderimpl Read for ChildStderrimpl<T: Read> Read for Take<T>impl<'a> Read for &'a UnixStreamimpl<T: Read, U: Read> Read for Chain<T, U>impl<R: ?Sized + Read> Read for BufReader<R>impl Read for &PipeReaderimpl<R: Read + ?Sized> Read for Box<R>