如何从Vec或切片读取(std::io::read)?
如何从Vec或切片读取(std::io::read)?,io,rust,traits,Io,Rust,Traits,Vecs支持std::io::Write,因此可以编写包含文件或Vec的代码。从API参考来看,它看起来既不支持Vec也不支持std::io::Read 有没有一个方便的方法来实现这一点?是否需要编写包装器结构 下面是一个工作代码的示例,它读取和写入一个文件,其中一行注释应该读取一个向量 use ::std::io; // Generic IO fn write_4_bytes<W>(mut file: W) -> Result<usize, io::Error>
Vec
s支持std::io::Write
,因此可以编写包含文件或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();
}
use::std::io;
//通用IO
fn写入4字节(mut文件:W)->结果
其中W:io::Write,
{
设len=file.write(b“1234”)?;
好的(len)
}
fn读取4字节(mut文件:R)->结果
其中R:io::Read,
{
让mut buf:[u8;4]=[0;4];
文件读取(&mut buf)?;
Ok(buf)
}
//特定类型
fn写入\读取\向量(){
让mut-vec_作为_文件:vec=vec::new();
{//Write
println!(“写入向量…{}”,写入4字节(&mut Vec_as_file).unwrap());
}
{//Read
//println!(“读取文件…{:?}”,读取4字节(&vec_as_文件).unwrap());
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
//注释上面的这一行以避免错误!
}
}
fn写入\读取\文件(){
让filepath=“temp.txt”;
{//Write
让mut file_作为_file=::std::fs::file::create(filepath).expect(“打开失败”);
println!(“写入文件…{}”,写入4字节(&mut File_as_File).unwrap());
}
{//Read
让mut file_作为_file=::std::fs::file::open(filepath).expect(“打开失败”);
println!(“读取文件…{:?}”,读取4字节(&mut File_as_File).unwrap());
}
}
fn main(){
写入读取向量();
写入读取文件();
}
此操作失败,错误如下:
error[E0277]:未满足特性绑定'std::vec::vec:std::io::Read'
-->src/main.rs:29:42
|
29 | println!(“正在读取文件…{:?}”,读取4字节(&vec_as_File).unwrap());
|^^^^^^^^^^^^^^未为'std::vec::vec'实现特性'std::io::Read'`
|
=注意:`read_4_bytes'需要`
我想为文件格式的编码器/解码器编写测试,而不必写入文件系统。虽然向量不支持std::io::Read
,但片支持
在某些情况下,Rust能够将Vec
强制转换为切片,但在其他情况下却不能,这造成了一些混乱
在这种情况下,需要对切片进行显式强制,因为在应用强制的阶段,编译器不知道Vec
没有实现Read
当使用以下方法之一将向量强制转换为切片时,问题中的代码将起作用:
读取4字节(&*vec\u作为文件)
读取4字节(&vec\u as\u文件[…])
读取4字节(vec\u as\u file.as\u slice())
注:
- 最初问这个问题时,我用的是
&Read
,而不是Read
。这使得传递对切片的引用失败,除非我传入了&&&vec_as_文件
,我认为这是不可能的
- rust的最新版本您还可以使用
as_slice()
将Vec转换为切片
- 感谢@arete on
#rust
找到了解决方案李>
std::io::游标
std::io::Cursor
是一个简单而有用的包装器,它为Vec
实现了Read
,因此它允许将vector用作可读实体
let mut file = Cursor::new(vector);
read_something(&mut 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);
}
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[..]);
}
从aboutstd::io::Cursor
:
游标通常与内存缓冲区一起使用,以允许它们执行读取和/或写入
标准库在常用作缓冲区的各种类型上实现了一些I/O特性,如Cursor
和Cursor
片
上述示例也适用于切片。在这种情况下,它将如下所示:
read_something(&mut &vector[..]);
工作示例:
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);
}
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[…]
是一个“对一个切片的可变引用”(对向量一部分的引用),因此我发现使用游标的显式选项更清晰、更优雅
光标切片
更重要的是:如果您有一个拥有缓冲区的游标
,并且您需要模拟(例如)“文件”的一部分,那么您可以从游标
获取一个切片
,并传递给函数
read_something(&mut &file.get_ref()[1..3]);
我已经删除了我的答案。这个问题现在比最初提出时要大得多,提供了更多的上下文。@simon whitehead,为最初没有给出一个全面的问题表示歉意,我想我可能遗漏了一些完全不需要工作代码示例的东西。在rust的最新版本中,您还可以使用as_slice()
将Vec
转换为slice,然后使用Read
中的方法。