如何从 Vec 或 Slice 读取 (std::io::Read)?
How to read (std::io::Read) from a Vec or Slice?
Vec
支持 std::io::Write
,因此可以编写带有 File
或 Vec
的代码。从 API 参考来看,Vec
和切片都不支持 std::io::Read
。
有什么方便的方法可以实现吗?是否需要编写包装器结构?
这是一个工作代码示例,它读取和写入一个文件,其中一行注释应该读取一个向量。
use ::std::io;
// Generic IO
fn write_4_bytes<W>(mut file: W) -> Result<usize, io::Error>
where W: io::Write,
{
let len = file.write(b"1234")?;
Ok(len)
}
fn read_4_bytes<R>(mut file: R) -> Result<[u8; 4], io::Error>
where R: io::Read,
{
let mut buf: [u8; 4] = [0; 4];
file.read(&mut buf)?;
Ok(buf)
}
// Type specific
fn write_read_vec() {
let mut vec_as_file: Vec<u8> = Vec::new();
{ // Write
println!("Writing Vec... {}", write_4_bytes(&mut vec_as_file).unwrap());
}
{ // Read
// println!("Reading File... {:?}", read_4_bytes(&vec_as_file).unwrap());
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
// Comment this line above to avoid an error!
}
}
fn write_read_file() {
let filepath = "temp.txt";
{ // Write
let mut file_as_file = ::std::fs::File::create(filepath).expect("open failed");
println!("Writing File... {}", write_4_bytes(&mut file_as_file).unwrap());
}
{ // Read
let mut file_as_file = ::std::fs::File::open(filepath).expect("open failed");
println!("Reading File... {:?}", read_4_bytes(&mut file_as_file).unwrap());
}
}
fn main() {
write_read_vec();
write_read_file();
}
失败并出现错误:
error[E0277]: the trait bound `std::vec::Vec<u8>: std::io::Read` is not satisfied
--> src/main.rs:29:42
|
29 | println!("Reading File... {:?}", read_4_bytes(&vec_as_file).unwrap());
| ^^^^^^^^^^^^ the trait `std::io::Read` is not implemented for `std::vec::Vec<u8>`
|
= note: required by `read_4_bytes`
我想为文件格式 encoder/decoder 编写测试,而不必写入文件系统。
虽然矢量不支持 std::io::Read
,但切片支持。
这里有些混乱,因为 Rust 在某些情况下能够将 Vec
强制转换为切片。
在这种情况下,需要对切片进行显式强制转换,因为在应用强制转换阶段,编译器不知道 Vec<u8>
不会 实施 Read
.
当使用以下方法之一将向量强制转换为切片时,问题中的代码将起作用:
read_4_bytes(&*vec_as_file)
read_4_bytes(&vec_as_file[..])
read_4_bytes(vec_as_file.as_slice())
.
注:
- 最初问这个问题时,我用的是
&Read
而不是 Read
。这使得传递对切片的引用失败,除非我传入了 &&*vec_as_file
,而我没想过要这样做。
- 最新版本的 Rust 也可以使用
as_slice()
将 Vec 转换为切片。
- 感谢
#rust
上的@arete 找到解决方案!
std::io::游标
std::io::Cursor
是一个简单而有用的包装器,它为 Vec<u8>
实现了 Read
,因此它允许将矢量用作可读实体。
let mut file = Cursor::new(vector);
read_something(&mut file);
并且 documentation 展示了如何使用 Cursor
而不是 File
来编写单元测试!
工作示例:
use std::io::Cursor;
use std::io::Read;
fn read_something(file: &mut impl Read) {
let _ = file.read(&mut [0; 8]);
}
fn main() {
let vector = vec![1, 2, 3, 4];
let mut file = Cursor::new(vector);
read_something(&mut file);
}
来自documentation 关于std::io::Cursor
:
Cursors are typically used with in-memory buffers to allow them to implement Read
and/or Write
...
The standard library implements some I/O traits on various types which are commonly used as a buffer, like Cursor<Vec<u8>>
and Cursor<&[u8]>
.
切片
上面的示例也适用于 切片 。在那种情况下,它将如下所示:
read_something(&mut &vector[..]);
工作示例:
use std::io::Read;
fn read_something(file: &mut impl Read) {
let _ = file.read(&mut [0; 8]);
}
fn main() {
let vector = vec![1, 2, 3, 4];
read_something(&mut &vector[..]);
}
&mut &vector[..]
是“对切片的可变引用”(对向量的一部分的引用的引用),所以我只是发现带有 Cursor
的显式选项更加清晰和优雅。
光标 <-> 切片
甚至更多:如果你有一个 Cursor
拥有一个缓冲区,并且你需要模拟,例如,“文件”的一部分,你可以从 slice
Cursor
并传递给函数。
read_something(&mut &file.get_ref()[1..3]);
Vec
支持 std::io::Write
,因此可以编写带有 File
或 Vec
的代码。从 API 参考来看,Vec
和切片都不支持 std::io::Read
。
有什么方便的方法可以实现吗?是否需要编写包装器结构?
这是一个工作代码示例,它读取和写入一个文件,其中一行注释应该读取一个向量。
use ::std::io;
// Generic IO
fn write_4_bytes<W>(mut file: W) -> Result<usize, io::Error>
where W: io::Write,
{
let len = file.write(b"1234")?;
Ok(len)
}
fn read_4_bytes<R>(mut file: R) -> Result<[u8; 4], io::Error>
where R: io::Read,
{
let mut buf: [u8; 4] = [0; 4];
file.read(&mut buf)?;
Ok(buf)
}
// Type specific
fn write_read_vec() {
let mut vec_as_file: Vec<u8> = Vec::new();
{ // Write
println!("Writing Vec... {}", write_4_bytes(&mut vec_as_file).unwrap());
}
{ // Read
// println!("Reading File... {:?}", read_4_bytes(&vec_as_file).unwrap());
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
// Comment this line above to avoid an error!
}
}
fn write_read_file() {
let filepath = "temp.txt";
{ // Write
let mut file_as_file = ::std::fs::File::create(filepath).expect("open failed");
println!("Writing File... {}", write_4_bytes(&mut file_as_file).unwrap());
}
{ // Read
let mut file_as_file = ::std::fs::File::open(filepath).expect("open failed");
println!("Reading File... {:?}", read_4_bytes(&mut file_as_file).unwrap());
}
}
fn main() {
write_read_vec();
write_read_file();
}
失败并出现错误:
error[E0277]: the trait bound `std::vec::Vec<u8>: std::io::Read` is not satisfied
--> src/main.rs:29:42
|
29 | println!("Reading File... {:?}", read_4_bytes(&vec_as_file).unwrap());
| ^^^^^^^^^^^^ the trait `std::io::Read` is not implemented for `std::vec::Vec<u8>`
|
= note: required by `read_4_bytes`
我想为文件格式 encoder/decoder 编写测试,而不必写入文件系统。
虽然矢量不支持 std::io::Read
,但切片支持。
这里有些混乱,因为 Rust 在某些情况下能够将 Vec
强制转换为切片。
在这种情况下,需要对切片进行显式强制转换,因为在应用强制转换阶段,编译器不知道 Vec<u8>
不会 实施 Read
.
当使用以下方法之一将向量强制转换为切片时,问题中的代码将起作用:
read_4_bytes(&*vec_as_file)
read_4_bytes(&vec_as_file[..])
read_4_bytes(vec_as_file.as_slice())
.
注:
- 最初问这个问题时,我用的是
&Read
而不是Read
。这使得传递对切片的引用失败,除非我传入了&&*vec_as_file
,而我没想过要这样做。 - 最新版本的 Rust 也可以使用
as_slice()
将 Vec 转换为切片。 - 感谢
#rust
上的@arete 找到解决方案!
std::io::游标
std::io::Cursor
是一个简单而有用的包装器,它为 Vec<u8>
实现了 Read
,因此它允许将矢量用作可读实体。
let mut file = Cursor::new(vector);
read_something(&mut file);
并且 documentation 展示了如何使用 Cursor
而不是 File
来编写单元测试!
工作示例:
use std::io::Cursor;
use std::io::Read;
fn read_something(file: &mut impl Read) {
let _ = file.read(&mut [0; 8]);
}
fn main() {
let vector = vec![1, 2, 3, 4];
let mut file = Cursor::new(vector);
read_something(&mut file);
}
来自documentation 关于std::io::Cursor
:
Cursors are typically used with in-memory buffers to allow them to implement
Read
and/orWrite
...The standard library implements some I/O traits on various types which are commonly used as a buffer, like
Cursor<Vec<u8>>
andCursor<&[u8]>
.
切片
上面的示例也适用于 切片 。在那种情况下,它将如下所示:
read_something(&mut &vector[..]);
工作示例:
use std::io::Read;
fn read_something(file: &mut impl Read) {
let _ = file.read(&mut [0; 8]);
}
fn main() {
let vector = vec![1, 2, 3, 4];
read_something(&mut &vector[..]);
}
&mut &vector[..]
是“对切片的可变引用”(对向量的一部分的引用的引用),所以我只是发现带有 Cursor
的显式选项更加清晰和优雅。
光标 <-> 切片
甚至更多:如果你有一个 Cursor
拥有一个缓冲区,并且你需要模拟,例如,“文件”的一部分,你可以从 slice
Cursor
并传递给函数。
read_something(&mut &file.get_ref()[1..3]);