Standard Input and Output
stdin()
std::io::stdin() constructs and returns a std::io::Stdin handle to the current process's standard input stream. Because Stdin is a zero-sized handle (0 bytes!) that references a static process-wide buffer protected by a Mutex, calling io::stdin() multiple times is free and always accesses the same shared stream.
Methods Directly on std::io::Stdin
| Method | Signature | Description |
|---|---|---|
io::stdin() |
pub const fn stdin() -> Stdin |
Returns a handle to the shared standard input stream |
.lock(&self) |
pub fn lock(&self) -> StdinLock<'static> |
Locks the global Stdin mutex and returns a BufRead-implementing guard with 'static lifetime! |
.read_line(&self, buf) |
pub fn read_line(&self, buf: &mut String) -> Result<usize> |
Locks Stdin, appends one line (including \n or \r\n) to buf, and returns the byte count read (0 on EOF) |
.lines(self) |
pub fn lines(self) -> Lines<StdinLock<'static>> |
Consumes Stdin, locks it, and returns an iterator yielding io::Result<String> lines (with \n / \r\n stripped!) |
.split(self, byte) |
pub fn split(self, byte: u8) -> Split<StdinLock<'static>> |
Returns an iterator splitting input on byte (such as b'\0' for xargs -0) |
Note: Since Rust 1.62, io::stdin().lock() returns StdinLock<'static> directly—so you no longer need to bind let stdin = io::stdin(); in a separate variable before calling stdin.lock()!
Comparing stdin().read_line(&mut buf) and stdin().lines()
`stdin().read_line(&mut buf)`:
- Appends to your existing `buf: String` (reuses heap capacity if you call `buf.clear()`!)
- KEEPS trailing `\n` or `\r\n` (use `buf.trim_end()` to strip)
- Returns `Ok(0)` at End-of-File (EOF)
`stdin().lines()`:
- Allocates a fresh `String` per line
- STRIPS trailing `\n` and `\r\n` automatically
- Ends iteration (`None`) at EOF
use std::io::{self, BufRead, Cursor};
fn parse_key_values(input: impl BufRead) -> io::Result<Vec<(String, String)>> {
let mut pairs = Vec::new();
// `.lines()` strips `\n` / `\r\n` automatically on any `BufRead` (including `stdin().lock()`):
for line_res in input.lines() {
let line = line_res?;
if let Some((k, v)) = line.split_once('=') {
pairs.push((k.trim().to_string(), v.trim().to_string()));
}
}
Ok(pairs)
}
fn main() -> io::Result<()> {
// Verify `io::stdin()` handle size and `StdinLock<'static>` acquisition:
let _stdin_lock: io::StdinLock<'static> = io::stdin().lock();
drop(_stdin_lock);
let mock_stdin = Cursor::new("host = 127.0.0.1\nport = 8080\r\n");
let parsed = parse_key_values(mock_stdin)?;
println!("size of io::Stdin: {} bytes", size_of::<io::Stdin>());
println!("parsed pairs: {:?}", parsed);
Ok(())
}
size of io::Stdin: 0 bytes
parsed pairs: [("host", "127.0.0.1"), ("port", "8080")]