Rust IO 操作简介

任何一门编程语言中 IO操作都是非常常见的内容. IO操作抽象了对实体的读写,该实体可以是任意类型,比如文件,内存,或者Socket。

典型的IO操作包含 读写操作,  大多数编程语言还会提供基于字符串的读写,  和基于缓冲的读写以提高性能

以Java为例,Java中定义了InputStream/OutputStream接口,包含一序列读写二进制的方法。

Reader/Writer则 提供了操作字符串的方法

BufferedInputStream/BufferedOutputStream,BufferedReader/BufferedWriter 提供了基于缓冲的读写

Rust也对IO操作提供了丰富的支持,位于std::io包下面

Rust标准库中的IO操作类主要有

Read/Write, BufRead trait

BufReader/BufWriter struct

相比于Java, 个人认为Rust的IO标准库API设计明显缺乏对称性和美感

比如说 Read trait中包含了对字节类型的读方法,也包含了直接读字符串的方法

但作为 对应的Write trait, 却只有对字节类型的写方法,而没有写字符串的方法

另外读方面有 BufRead trait, 但写的却没有 BufWrite trait

总体感觉API设计明显不如Java清晰

 Rust 标准库中,IO的具体实现有File,Cursor(实现了BufRead), 和 TcpStream

下面是个例子

use std::io;
use std::io::prelude::*;
use std::fs::File;

fn main() -> io::Result<()> {
   let mut f = File::open("foo.txt")?;
   let mut buffer = [0; 10];

   // read up to 10 bytes
   let n = f.read(&mut buffer)?;

   println!("The bytes: {:?}", &buffer[..n]);
   Ok(())
}

 对于BufWriter来说,需要注意2点

1. BufWriter对于内存的读写没有任何优势,这时可以直接用Write. 只对多次分批写入非内存对象时,有性能优势。

2. 在BufWriter被drop之前,需要手动的调用flush, 以确保数据已经写入。因为BufWriter 被drop时,虽然也会调用flush,但如果flush失败,rust是不会有任何错误通知的。

使用BufWriter的例子

第一种,不使用BufWriter, 性能会比较差
use std::io::prelude::*;
use std::net::TcpStream;

let mut stream = TcpStream::connect("127.0.0.1:34254").unwrap();

for i in 0..10 {
   stream.write(&[i+1]).unwrap();
}


第二种, 使用BufWriter, 性能会好很多
use std::io::prelude::*;
use std::io::BufWriter;
use std::net::TcpStream;

let mut stream = BufWriter::new(TcpStream::connect("127.0.0.1:34254").unwrap());

for i in 0..10 {
   stream.write(&[i+1]).unwrap();
}
stream.flush().unwrap();

 

Rust标准库非常的小,没有提供基于内存实现的Read/Write, 只能跑去第三方crate  Bytes了

该crate自己定义了一组 Read/Write,  Reader/Writer,方便操作内存数据

use bytes::Buf;
use std::io;

let mut buf = b"hello world".reader();
let mut dst = vec![];

io::copy(&mut buf, &mut dst).unwrap();

let buf = buf.into_inner();
assert_eq!(0, buf.remaining());

 


上一篇:算法|最大公约数


下一篇:Rust从入门到劝退 ( 一 )