Standard Input and Output

stdout()

std::io::stdout() constructs and returns a zero-sized std::io::Stdout handle to the process's standard output stream. It implements std::io::Write and std::io::IsTerminal, and provides .lock() to obtain an exclusive StdoutLock<'static> guard.

Methods and Traits on std::io::Stdout

Method / Trait Signature Behavior
io::stdout() pub const fn stdout() -> Stdout Returns a handle to the shared standard output stream (0 bytes)
.lock(&self) pub fn lock(&self) -> StdoutLock<'static> Acquires the global re-entrant stdout lock for batch writing
Write::write(&mut self, buf) fn write(&mut self, buf: &[u8]) -> Result<usize> Writes bytes to the internal LineWriter (flushes on \n)
Write::write_all(&mut self, buf) fn write_all(&mut self, buf: &[u8]) -> Result<()> Loops until all bytes of buf are written
Write::write_fmt(&mut self, fmt) fn write_fmt(&mut self, fmt: Arguments<'_>) -> Result<()> Invoked by write!(stdout, ...) and writeln!(stdout, ...)
Write::flush(&mut self) fn flush(&mut self) -> Result<()> Flushes buffered bytes out to OS file descriptor 1
IsTerminal::is_terminal(&self) fn is_terminal(&self) -> bool Returns true if stdout is connected to an interactive terminal (TTY)

Re-Entrancy of StdoutLock with println!

Because Stdout uses a re-entrant lock internally on the current thread, calling a helper function that uses println! while the same thread already holds let mut lock = io::stdout().lock(); will not deadlock! (Another thread calling println! or stdout().lock() will block until the first thread's StdoutLock is dropped.)

use std::io::{self, Write};

fn main() -> io::Result<()> {
    let mut lock: io::StdoutLock<'static> = io::stdout().lock();

    writeln!(lock, "1. Writing directly through StdoutLock")?;
    // Safe on the same thread because `Stdout` uses a re-entrant lock:
    println!("2. Nested println! on the same thread does not deadlock");
    writeln!(lock, "3. Final line through StdoutLock")?;

    lock.flush()?;
    Ok(())
}
1. Writing directly through StdoutLock
2. Nested println! on the same thread does not deadlock
3. Final line through StdoutLock

Writing Binary Data Directly to stdout()

Whereas print! and println! only format valid UTF-8 strings, calling io::stdout().write_all(bytes) writes arbitrary raw binary data (such as compressed archives, PNG images, or protobuf frames) directly to standard output:

use std::io::{self, Write};

fn main() -> io::Result<()> {
    let raw_ascii_bytes: &[u8] = b"RAW_BYTES_OK\n";
    io::stdout().write_all(raw_ascii_bytes)?;
    io::stdout().flush()?;
    Ok(())
}
RAW_BYTES_OK