diff --git a/src/libstd/io/mod.rs b/src/libstd/io/mod.rs index 2447473103101..3016cfa8fe5e3 100644 --- a/src/libstd/io/mod.rs +++ b/src/libstd/io/mod.rs @@ -9,6 +9,235 @@ // except according to those terms. //! 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`][read] and [`Write`][write] traits, which provide the +//! most general interface for reading and writing input and output. +//! +//! [read]: trait.Read.html +//! [write]: trait.Write.html +//! +//! # Read and Write +//! +//! Because they are traits, they're 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 somtimes even `Vec`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 foo() -> io::Result<()> { +//! let mut f = try!(File::open("foo.txt")); +//! let mut buffer = [0; 10]; +//! +//! // read up to 10 bytes +//! try!(f.read(&mut buffer)); +//! +//! println!("The bytes: {:?}", buffer); +//! # Ok(()) +//! # } +//! ``` +//! +//! `Read` 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`][seek] +//! and [`BufRead`][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 foo() -> io::Result<()> { +//! let mut f = try!(File::open("foo.txt")); +//! let mut buffer = [0; 10]; +//! +//! // skip to the last 10 bytes of the file +//! try!(f.seek(SeekFrom::End(-10))); +//! +//! // read up to 10 bytes +//! try!(f.read(&mut buffer)); +//! +//! println!("The bytes: {:?}", buffer); +//! # Ok(()) +//! # } +//! ``` +//! +//! [seek]: trait.Seek.html +//! [bufread]: trait.BufRead.html +//! +//! `BufRead` 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 foo() -> io::Result<()> { +//! let f = try!(File::open("foo.txt")); +//! let mut reader = BufReader::new(f); +//! let mut buffer = String::new(); +//! +//! // read a line into buffer +//! try!(reader.read_line(&mut buffer)); +//! +//! println!("{}", buffer); +//! # Ok(()) +//! # } +//! ``` +//! +//! `BufWriter` doesn't add any new ways of writing, it just buffers every call +//! to [`write()`][write]: +//! +//! ``` +//! use std::io; +//! use std::io::prelude::*; +//! use std::io::BufWriter; +//! use std::fs::File; +//! +//! # fn foo() -> io::Result<()> { +//! let f = try!(File::create("foo.txt")); +//! { +//! let mut writer = BufWriter::new(f); +//! +//! // write a byte to the buffer +//! try!(writer.write(&[42])); +//! +//! } // the buffer is flushed once writer goes out of scope +//! +//! # Ok(()) +//! # } +//! ``` +//! +//! [write]: trait.Write.html#tymethod.write +//! +//! ## Standard input and output +//! +//! A very common source of input is standard input: +//! +//! ``` +//! use std::io; +//! +//! # fn foo() -> io::Result<()> { +//! let mut input = String::new(); +//! +//! try!(io::stdin().read_line(&mut input)); +//! +//! println!("You typed: {}", input.trim()); +//! # Ok(()) +//! # } +//! ``` +//! +//! And a very common source of output is standard output: +//! +//! ``` +//! use std::io; +//! use std::io::prelude::*; +//! +//! # fn foo() -> io::Result<()> { +//! try!(io::stdout().write(&[42])); +//! # Ok(()) +//! # } +//! ``` +//! +//! Of course, using `io::stdout()` directly is less comon 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 foo() -> io::Result<()> { +//! let f = try!(File::open("foo.txt")); +//! let mut reader = BufReader::new(f); +//! +//! for line in reader.lines() { +//! let line = try!(line); +//! println!("{}", line); +//! } +//! +//! # Ok(()) +//! # } +//! ``` +//! +//! ## Functions +//! +//! There are a number of [functions][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 foo() -> io::Result<()> { +//! try!(io::copy(&mut io::stdin(), &mut io::stdout())); +//! # Ok(()) +//! # } +//! ``` +//! +//! [functions]: #functions +//! +//! ## io::Result +//! +//! Last, but certainly not least, is [`io::Result`][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 [`try!`][try] macro: +//! +//! ``` +//! use std::io; +//! +//! fn read_input() -> io::Result<()> { +//! let mut input = String::new(); +//! +//! try!(io::stdin().read_line(&mut input)); +//! +//! println!("You typed: {}", input.trim()); +//! +//! Ok(()) +//! } +//! ``` +//! +//! The 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 use `()`. +//! +//! [result]: type.Result.html +//! [try]: macro.try!.html #![stable(feature = "rust1", since = "1.0.0")]