Skip to content

Ch 19: Read trait

Read是Rust中用于读取字节流的trait。所有表示输入源的类型都实现了这个trait:

  • File - 文件
  • TcpStream - TCP socket
  • std::io::stdin - 标准输入
  • Cursor<&[u8]> - 内存中的字节切片
  • Vec<u8> - 实现了Read用于读取

Read trait定义了在std::io模块中,是Rust I/O系统的核心。

pub trait Read {
fn read(&mut self, buf: &mut [u8]) -> Result<usize>;
fn read_to_end(&mut self, buf: &mut Vec<u8>) -> Result<usize>;
fn read_to_string(&mut self, buf: &mut String) -> Result<usize>;
// 还有其他方法...
}

read是最基本的读取方法,将数据读入缓冲区:

use std::io::{Read, Cursor};
fn main() -> std::io::Result<()> {
let data = b"hello world";
let mut cursor = Cursor::new(data);
let mut buffer = [0u8; 1024];
// read 返回读取的字节数
let n = cursor.read(&mut buffer)?;
println!("读取了 {} 字节", n);
println!("内容: {:?}", &buffer[..n]);
Ok(())
}

注意:read可能返回比请求的更少的字节(例如网络读取)。

将所有剩余数据读入Vec:

use std::io::{Read, Cursor};
fn main() -> std::io::Result<()> {
let data = b"hello world";
let mut cursor = Cursor::new(data);
let mut vec = Vec::new();
cursor.read_to_end(&mut vec)?;
println!("读取到Vec: {:?}", vec);
println!("字符串: {}", String::from_utf8_lossy(&vec));
Ok(())
}

直接读取到String:

use std::io::{Read, Cursor};
fn main() -> std::io::Result<()> {
let data = b"hello world";
let mut cursor = Cursor::new(data);
let mut s = String::new();
cursor.read_to_string(&mut s)?;
println!("字符串: {}", s);
Ok(())
}

Read本身没有read_line,它是在BufRead trait中提供的。我们将在下一章学习。

返回字节迭代器:

use std::io::{Read, Cursor};
fn main() -> std::io::Result<()> {
let data = b"hello";
let mut cursor = Cursor::new(data);
// bytes 返回迭代器
for byte in cursor.bytes() {
print!("{} ", byte?);
}
println!();
// 输出: 104 101 108 108 111
Ok(())
}
use std::io::{Read, Cursor};
fn main() -> std::io::Result<()> {
let data = b"hello world";
let mut cursor = Cursor::new(data);
// read_exact 读取精确字节数
let mut buffer = [0u8; 5];
cursor.read_exact(&mut buffer)?;
println!("read_exact: {:?}", buffer);
println!("字符串: {}", String::from_utf8_lossy(&buffer));
Ok(())
}

如果数据不足,read_exact会返回错误。

use std::io::{Read, Cursor};
fn main() -> std::io::Result<()> {
let data = b"hello world";
let mut cursor = Cursor::new(data);
// take 限制读取的字节数
let mut limited = cursor.take(5);
let mut buffer = [0u8; 1024];
let n = limited.read(&mut buffer)?;
println!("读取了 {} 字节: {:?}", n, &buffer[..n]);
Ok(())
}
use std::io::{Read, Cursor};
fn main() -> std::io::Result<()> {
let data1 = b"hello";
let data2 = b" world";
let mut cursor1 = Cursor::new(data1);
let mut cursor2 = Cursor::new(data2);
let mut combined = cursor1.chain(cursor2);
let mut buffer = [0u8; 1024];
let n = combined.read(&mut buffer)?;
println!("chain读取: {:?}", String::from_utf8_lossy(&buffer[..n]));
// 输出: chain读取: "hello world"
Ok(())
}
use std::fs::File;
use std::io::{Read, BufReader};
fn main() -> std::io::Result<()> {
let file = File::open("Cargo.toml")?;
let mut reader = BufReader::new(file);
let mut contents = String::new();
reader.read_to_string(&mut contents)?;
println!("文件内容 (前100字符):");
for line in contents.lines().take(5) {
println!("{}", line);
}
Ok(())
}
use std::io::{Read, Cursor};
fn main() {
let data: &[u8] = &[];
let mut cursor = Cursor::new(data);
let mut buffer = [0u8; 1024];
// read返回Result
match cursor.read(&mut buffer) {
Ok(n) => println!("读取了 {} 字节", n),
Err(e) => println!("读取错误: {}", e),
}
// read_to_end同样返回Result
let mut vec = Vec::new();
if let Err(e) = cursor.read_to_end(&mut vec) {
println!("read_to_end错误: {}", e);
}
}
类型说明
File文件
TcpStreamTCP连接
BufReader<T>带缓冲的读取器
Cursor<T>内存中的数据
std::io::stdin标准输入
Chain<T, U>链式读取器
Take<T>限制读取量

今天我们学习了Read trait:

  1. read - 将数据读入缓冲区,返回读取字节数
  2. read_to_end - 读取所有剩余数据到Vec
  3. read_to_string - 直接读取到String
  4. read_exact - 读取精确字节数
  5. bytes - 返回字节迭代器
  6. take - 限制读取量
  7. chain - 链式连接两个读取器

Read是Rust I/O的基础trait,理解它的用法对文件操作、网络编程等场景至关重要。