341: Buffered Stream
Difficulty: Intermediate Category: IO Concept: BufReader/BufWriter wrapping stdin/stdout Key Insight: Buffering reduces system calls โ wrapping raw I/O in buffers is essential for performance// 341: Buffered Stream
// BufReader/BufWriter wrapping for efficient I/O
use std::io::{self, BufRead, BufWriter, Write, BufReader, Cursor};
// Approach 1: BufReader for efficient reading
fn count_lines(input: &[u8]) -> usize {
let reader = BufReader::new(input);
reader.lines().count()
}
fn read_lines(input: &[u8]) -> Vec<String> {
let reader = BufReader::new(input);
reader.lines().filter_map(|l| l.ok()).collect()
}
// Approach 2: BufWriter for efficient writing
fn write_lines(lines: &[&str]) -> Vec<u8> {
let mut output = Vec::new();
{
let mut writer = BufWriter::new(&mut output);
for line in lines {
writeln!(writer, "{}", line).unwrap();
}
writer.flush().unwrap();
}
output
}
// Approach 3: String building with buffered writes
fn build_csv(headers: &[&str], rows: &[Vec<String>]) -> String {
let mut buf = Vec::new();
{
let mut writer = BufWriter::new(&mut buf);
writeln!(writer, "{}", headers.join(",")).unwrap();
for row in rows {
writeln!(writer, "{}", row.join(",")).unwrap();
}
writer.flush().unwrap();
}
String::from_utf8(buf).unwrap()
}
fn main() {
let input = b"hello\nworld\ntest\n";
println!("lines: {}", count_lines(input));
println!("read: {:?}", read_lines(input));
let output = write_lines(&["hello", "world"]);
println!("written: {:?}", String::from_utf8(output).unwrap());
let csv = build_csv(
&["name", "age"],
&[vec!["Alice".into(), "30".into()], vec!["Bob".into(), "25".into()]],
);
println!("csv:\n{}", csv);
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_count_lines() {
assert_eq!(count_lines(b"a\nb\nc\n"), 3);
assert_eq!(count_lines(b""), 0);
}
#[test]
fn test_read_lines() {
let lines = read_lines(b"hello\nworld\n");
assert_eq!(lines, vec!["hello", "world"]);
}
#[test]
fn test_write_lines() {
let output = write_lines(&["hello", "world"]);
let s = String::from_utf8(output).unwrap();
assert!(s.contains("hello"));
assert!(s.contains("world"));
}
#[test]
fn test_csv() {
let csv = build_csv(&["a", "b"], &[vec!["1".into(), "2".into()]]);
assert!(csv.starts_with("a,b\n"));
assert!(csv.contains("1,2"));
}
}
(* 341: Buffered Stream *)
(* OCaml channels are already buffered by default *)
(* Approach 1: Buffered input *)
let read_lines_buffered ic =
let rec aux acc =
match input_line ic with
| line -> aux (line :: acc)
| exception End_of_file -> List.rev acc
in
aux []
(* Approach 2: Buffered output *)
let write_lines_buffered oc lines =
List.iter (fun line ->
output_string oc line;
output_char oc '\n'
) lines;
flush oc
(* Approach 3: Buffer module for string building *)
let build_string parts =
let buf = Buffer.create 256 in
List.iter (fun s ->
Buffer.add_string buf s;
Buffer.add_char buf '\n'
) parts;
Buffer.contents buf
(* Tests *)
let () =
let result = build_string ["hello"; "world"; "test"] in
assert (result = "hello\nworld\ntest\n");
let buf = Buffer.create 16 in
Buffer.add_string buf "abc";
Buffer.add_string buf "def";
assert (Buffer.contents buf = "abcdef");
Printf.printf "โ All tests passed\n"
๐ Detailed Comparison
Core Insight
Buffering reduces system calls โ wrapping raw I/O in buffers is essential for performance
OCaml Approach
- See example.ml for implementation
Rust Approach
- See example.rs for implementation
Comparison Table
| Feature | OCaml | Rust |
|---|---|---|
| See | example.ml | example.rs |