Skip to content

Ch 20: Write trait

Write是Rust中用于写入字节流的trait。与Read相对,Write trait用于所有输出目标:

  • File - 文件
  • TcpStream - TCP socket
  • std::io::stdout - 标准输出
  • Vec<u8> - 内存缓冲区

Write trait同样定义在std::io模块中。

pub trait Write {
fn write(&mut self, buf: &[u8]) -> Result<usize>;
fn write_all(&mut self, buf: &[u8]) -> Result<()>;
fn flush(&mut self) -> Result<()>;
// 其他方法...
}

write是最基本的写入方法:

use std::io::{Write, Cursor};
fn main() -> std::io::Result<()> {
let mut cursor = Cursor::new(Vec::new());
// write 返回写入的字节数(可能少于请求的)
let n = cursor.write(b"hello")?;
println!("write返回: {} 字节", n);
// 获取写入的内容
println!("cursor内容: {:?}", cursor.get_ref());
Ok(())
}

注意:write可能返回比请求更少的字节,调用者需要处理这种情况。

写入所有数据:

use std::io::{Write, Cursor};
fn main() -> std::io::Result<()> {
let mut cursor = Cursor::new(Vec::new());
// write_all 确保写入所有数据
cursor.write_all(b"hello world")?;
cursor.write_all(b"!")?;
println!("写入内容: {:?}", cursor.get_ref());
// 输出: [104, 101, 108, 108, 111, 32, 119, 111, 114, 108, 100, 33]
Ok(())
}

将缓冲区数据刷新到实际目标:

use std::io::{Write, Cursor};
fn main() -> std::io::Result<()> {
let mut cursor = Cursor::new(Vec::new());
cursor.write_all(b"hello")?;
// flush 确保数据被写出
cursor.flush()?;
println!("flush完成");
Ok(())
}

重要:对于文件和网络连接,flush之前数据可能还在缓冲区。

use std::io::Write;
fn main() -> std::io::Result<()> {
let mut stdout = std::io::stdout();
// writeln! 格式化写入并换行
writeln!(stdout, "Hello, {}!", "world")?;
writeln!(stdout, "数字: {}, 字符: {}", 42, 'A')?;
stdout.flush()?;
Ok(())
}

BufWriter包装Writer,提供写入缓冲:

use std::io::{Write, BufWriter, Cursor};
fn main() -> std::io::Result<()> {
let file = File::create("output.txt")?;
let mut buffered = BufWriter::new(file);
// 多次小写入会被缓冲
for i in 0..1000 {
writeln!(buffered, "行 {}", i)?;
}
// drop或flush时数据被写出
buffered.flush()?;
println!("写入完成");
Ok(())
}
use std::io::Write;
fn main() -> std::io::Result<()> {
let mut stdout = std::io::stdout();
// write_fmt 使用格式化宏
stdout.write_fmt(format_args!("{:#?}", [1, 2, 3]))?;
stdout.write_all(b"\n")?;
stdout.flush()?;
Ok(())
}
use std::io::{BufWriter, BufWriter, File};
fn main() -> std::io::Result<()> {
let file = File::create("large_output.txt")?;
let mut writer = BufWriter::new(file);
// 设置更大的缓冲区
writer.get_ref();
// 写入大量数据
for i in 0..10000 {
writeln!(writer, "数据行 {}", i)?;
}
writer.flush()?;
Ok(())
}
use std::io::{Write, BufWriter, Cursor};
fn main() -> std::io::Result<()> {
let mut cursor = Cursor::new(Vec::new());
let mut writer = BufWriter::new(&mut cursor);
writer.write_all(b"hello")?;
writeln!(writer, " world")?;
// into_inner 获取底层Writer
// 注意:需要先flush
writer.flush()?;
let inner = writer.into_inner().unwrap();
println!("inner: {:?}", inner.get_ref());
Ok(())
}
use std::io::{self, Write};
struct Counter {
count: usize,
}
impl Write for Counter {
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
self.count += buf.len();
Ok(buf.len())
}
fn flush(&mut self) -> io::Result<()> {
Ok(())
}
}
fn main() -> io::Result<()> {
let mut counter = Counter { count: 0 };
counter.write_all(b"hello")?;
counter.write_all(b" world")?;
println!("写入的字节数: {}", counter.count);
Ok(())
}
类型说明
File文件
TcpStreamTCP连接
BufWriter<T>带缓冲的写入器
std::io::stdout标准输出
std::io::stderr标准错误
Vec<u8>内存缓冲区
use std::io::Write;
fn main() -> std::io::Result<()> {
let mut stdout = std::io::stdout();
// write返回Result,需要处理
match stdout.write(b"hello") {
Ok(n) => println!("写入 {} 字节", n),
Err(e) => eprintln!("写入错误: {}", e),
}
// 通常使用?操作符传播错误
stdout.write_all(b" world")?;
stdout.flush()?;
Ok(())
}

今天我们学习了Write trait:

  1. write - 写入数据到缓冲区,返回写入字节数
  2. write_all - 确保写入所有数据
  3. flush - 刷新缓冲区到目标
  4. BufWriter - 包装Writer提供缓冲,减少系统调用
  5. writeln! - 格式化写入并换行
  6. write_fmt - 格式化参数写入

Write trait是Rust I/O系统的重要组成部分,正确使用flush和BufWriter可以显著提高写入性能。