如何在Rust中创建可用作Reader,Writer或Seek的内存中对象?

lis*_*szt 29 in-memory rust

我需要一个完全内存中的对象,我可以给予BufReaderBufWriter.像Python这样的东西StringIO.我想使用通常与Files 一起使用的方法来写入和读取这样的对象.

有没有办法使用标准库?

Luk*_*odt 36

事实上有一种方法.见面Cursor<T>!

在文档中,您可以看到有以下impls:

impl<T> Seek for Cursor<T> where T: AsRef<[u8]>
impl<T> Read for Cursor<T> where T: AsRef<[u8]>
impl Write for Cursor<Vec<u8>>
impl<T> AsRef<[T]> for Vec<T>
Run Code Online (Sandbox Code Playgroud)

从这里就可以看出,您可以使用的类型Cursor<Vec<u8>>,就像一个普通的文件,因为Read,Write以及Seek该类型的实现!

小例子(游乐场):

use std::io::{Cursor, Read, Seek, SeekFrom, Write};

// Create fake "file"
let mut c = Cursor::new(Vec::new());

// Write into the "file" and seek to the beginning
c.write_all(&[1, 2, 3, 4, 5]).unwrap();
c.seek(SeekFrom::Start(0)).unwrap();

// Read the "file's" contents into a vector
let mut out = Vec::new();
c.read_to_end(&mut out).unwrap();

println!("{:?}", out);
Run Code Online (Sandbox Code Playgroud)

有关更有用的示例,请查看上面链接的文档.


She*_*ter 8

Cursor 大部分时间都不需要.

我能给予的对象BufReaderBufWriter

BufReader需要一个实现的值Read:

impl<R: Read> BufReader<R> {
    pub fn new(inner: R) -> BufReader<R>
}
Run Code Online (Sandbox Code Playgroud)

BufWriter需要一个实现的值Write:

impl<W: Write> BufWriter<W> {
    pub fn new(inner: W) -> BufWriter<W> {}
}
Run Code Online (Sandbox Code Playgroud)

如果你查看Read你会发现的实现者impl<'a> Read for &'a [u8].

如果您查看实现者Write,您会发现impl Write for Vec<u8>.

use std::io::{Read, Write};

fn main() {
    // Create fake "file"
    let mut file = Vec::new();

    // Write into the "file"
    file.write_all(&[1, 2, 3, 4, 5]).unwrap();

    // Read the "file's" contents into a new vector
    let mut out = Vec::new();
    let mut c = file.as_slice();
    c.read_to_end(&mut out).unwrap();

    println!("{:?}", out);
}
Run Code Online (Sandbox Code Playgroud)

写入一个Vec将永远贴在最后.我们还会对Vec可以更新的内容进行分析.每次读取c将进一步前进切片直到它为空.

主要区别来自Cursor:

  • 无法查找数据,因此无法轻松重新读取数据
  • 除了最后,不能写到任何地方

  • @liszt 不,这些实现存在于 Rust 1.0 中。 (2认同)

Ale*_*lar 6

如果要BufReader与内存一起使用String,可以使用以下as_bytes()方法:

use std::io::BufRead;
use std::io::BufReader;
use std::io::Read;

fn read_buff<R: Read>(mut buffer: BufReader<R>) {
    let mut data = String::new();
    let _ = buffer.read_line(&mut data);

    println!("read_buff got {}", data);
}

fn main() {
    read_buff(BufReader::new("Potato!".as_bytes()));
}
Run Code Online (Sandbox Code Playgroud)

打印read_buff got Potato!。在这种情况下,无需使用游标。

要使用内存StringBufWriter,你可以使用as_mut_vec方法。不幸的是unsafe,我没有找到其他方法。我不喜欢这种Cursor方法,因为它消耗了向量,并且我还没有找到一种将和Cursor一起使用的方法BufWriter

use std::io::BufWriter;
use std::io::Write;

pub fn write_something<W: Write>(mut buf: BufWriter<W>) {
    buf.write("potato".as_bytes());
}

#[cfg(test)]
mod tests {
    use super::*;
    use std::io::{BufWriter};

    #[test]
    fn testing_bufwriter_and_string() {
        let mut s = String::new();

        write_something(unsafe { BufWriter::new(s.as_mut_vec()) });

        assert_eq!("potato", &s);
    }
}
Run Code Online (Sandbox Code Playgroud)