【发布时间】:2017-04-25 11:45:19
【问题描述】:
我需要一个完全在内存中的对象,我可以将它提供给BufReader 和BufWriter。类似于 Python 的StringIO。我想使用通常与Files 一起使用的方法来写入和读取这样的对象。
有没有办法使用标准库来做到这一点?
【问题讨论】:
我需要一个完全在内存中的对象,我可以将它提供给BufReader 和BufWriter。类似于 Python 的StringIO。我想使用通常与Files 一起使用的方法来写入和读取这样的对象。
有没有办法使用标准库来做到这一点?
【问题讨论】:
其实有办法:Cursor<T>!
(也请阅读 Shepmaster's answer 了解为什么它更容易)
在文档中你可以看到有以下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>
由此您可以看到您可以像普通文件一样使用Cursor<Vec<u8>> 类型,因为Read、Write 和Seek 是针对该类型实现的!
小例子(Playground):
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);
有关更有用的示例,请查看上面链接的文档。
【讨论】:
如果您想将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()));
}
这将打印read_buff got Potato!。这种情况下不需要使用游标。
要将内存中的String 与BufWriter 一起使用,您可以使用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);
}
}
【讨论】:
Cursor后,您可以get the Vec back。
from_utf8 转换为字符串,from_utf8 似乎避免了向量的复制,所以它应该是有效的,也可以使用 `from_utf8_unchecked' 这应该是一个简单的举动。
你不需要Cursor大部分时间。
我可以给
BufReader和BufWriter的对象
BufReader 需要一个实现Read 的值:
impl<R: Read> BufReader<R> {
pub fn new(inner: R) -> BufReader<R>
}
BufWriter 需要一个实现Write 的值:
impl<W: Write> BufWriter<W> {
pub fn new(inner: W) -> BufWriter<W> {}
}
如果你查看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);
}
写入Vec 将始终附加到末尾。我们还对可以更新的Vec 进行了切片。每次读取c 都会使切片进一步前进,直到它为空。
与Cursor的主要区别:
【讨论】: