如何写BufWriter并获取所写的内容?

时间:2018-10-26 15:23:06

标签: rust

是否可以使用Writer并将内容写回给写作者?像BufWriterReader一样?我已经尝试过了,但是没有编译:

#[test]
fn write_to_json_test0() {
    let json = get_schema_without_optionals0(); // this is a thing serde_json can (de)serialize
    let buf = Vec::new();
    let writer = BufWriter::new(buf); // buf moves here

    serde_json::to_writer(writer, &json).unwrap(); // writer moves here

    let s = String::from_utf8(writer.into_inner().unwrap()).unwrap(); // compile error, because writer used after move

    assert_eq!(s, json.to_string());
}

a pull-request for a BufWriter::buffer(),但现在不可用。

测试to_string()to_writer()是否返回相同值的最快方法是什么?我真的需要写文件并将文件读取为字符串吗?

2 个答案:

答案 0 :(得分:3)

  

测试to_string()to_writer()是否返回相同值的最快方法

the source code for to_string

let vec = try!(to_vec(value));
let string = unsafe {
    // We do not emit invalid UTF-8.
    String::from_utf8_unchecked(vec)
};
Ok(string)

打给to_vec的人:

let mut writer = Vec::with_capacity(128);
try!(to_writer(&mut writer, value));
Ok(writer)

粘在一起,几乎与您的代码相同:

let mut writer = Vec::with_capacity(128);
to_writer(&mut writer, value)?;
let string = unsafe {
    // We do not emit invalid UTF-8.
    String::from_utf8_unchecked(writer)
};
Ok(string)

但是效率更高:

  • 它在Vec
  • 中预先分配了一些空间
  • 它避免使用BufWriter(如 Sven Marnach points out
  • 它跳过UTF-8有效性检查
  

BufWriter::buffer()的拉取请求

否,在合并并释放该拉取请求之前,您无法访问BufWriter的缓冲区-这是添加该请求的部分原因!

  

写给这位作家

您似乎并不完全了解BufWriter的目的。它缓冲写入您的数据,以便基础写入器获得它。缓冲区中的数据是基础编写器未看到的数据。您引用的请求请求不会帮助您

实际上,在尝试将基础flush解析为字符串之前,您需要确保BufWriter Vec以确保缓冲区中没有数据。幸运的是,into_inner已经为您做到了。

  

作家搬到这里

这是因为Serde遵循“ C-RW-VALUE”准则:Generic reader/writer functions take R: Read and W: Write by value。您可以使用Write::by_ref来避免放弃作者的所有权:

#[test]
fn write_to_json_test0() -> Result<(), io::Error> {
    let json = Value::Number(42.into());

    let buf = Vec::new();
    let mut writer = BufWriter::new(buf);
    serde_json::to_writer(writer.by_ref(), &json)?;
    let s = String::from_utf8(writer.into_inner()?).unwrap();

    assert_eq!(s, json.to_string());
    Ok(())
}

之所以可行,是因为by_ref返回了对编写者的可变引用,并且any mutable reference to a type that itself implements WriteWrite有一个空白实现

impl<'a, W: Write + ?Sized> Write for &'a mut W

by_ref只是一种便利功能,可以避免显式地获取可变引用的相对奇怪的语法。 by_refRead都重复这种Iterator模式。

另请参阅:

答案 1 :(得分:2)

有一个forwarding implementation of Write for mutable references to Write

impl<'a, W: Write + ?Sized> Write for &'a mut W

使用此实现,您可以通过移动可变引用来避免移动buf或移动writer

请注意,将Vec<u8>包裹在BufWriter中并不是很有用。缓冲旨在减少对慢速后端的写入次数,但是无论如何,如果后端是内存,那么添加一层缓冲都不会有任何好处。

如果我们删除BufWriter,则您的代码应如下所示:

fn write_to_json_test0() {
    let json = get_schema_without_optionals0();
    let mut buf = Vec::new();
    serde_json::to_writer(&mut buf, &json).unwrap();
    let s = String::from_utf8(buf).unwrap();
    assert_eq!(s, json.to_string());
}