Rust IO 操作简介

Rust IO 操作简介

Posted by     "Rock Huang" on Sunday, June 2, 2024

概述

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

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

Rust IO 操作简介 2024-04-09 21:09·逍遥游 任何一门编程语言中 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());

「真诚赞赏,手留余香」

Rock Blog

真诚赞赏,手留余香

使用微信扫描二维码完成支付