io - 我应该如何阅读有关字节序的文件内容?

标签 io coding-style rust endianness idioms

我可以看到,在 Rust 中,我可以通过以下方式将文件读取为字节数组:

File::open(&Path::new("fid")).read_to_end();

我也可以只读取一个大端或小端格式的 u32:

File::open(&Path::new("fid")).read_be_u32();
File::open(&Path::new("fid")).read_le_u32();

但据我所知,我将不得不做这样的事情(简化):

let path = Path::new("fid");                         
let mut file = File::open(&path);                                                         
let mut v = vec![];                                  
for n in range(1u64, path.stat().unwrap().size/4u64){
    v.push(if big {                                  
        file.read_be_u32()                           
    } else {                                         
        file.read_le_u32()                           
    });                                              
}

但这太丑陋了,我只是想知道是否有更好的方法来做到这一点。

好的,所以循环中的 if 是丑陋的一大部分,所以我按照建议提升了它,新版本如下:

let path = Path::new("fid");
let mut file = File::open(&path);
let mut v = vec![];
let fun = if big {
    ||->IoResult<u32>{file.read_be_u32()}
} else {
    ||->IoResult<u32>{file.read_le_u32()}
};
for n in range(1u64, path.stat().unwrap().size/4u64){
    v.push(fun());
}

了解了 range_step 和使用 _ 作为索引,所以现在我剩下:

let path = Path::new("fid");
let mut file = File::open(&path);
let mut v = vec![];
let fun = if big {
    ||->IoResult<u32>{file.read_be_u32()}
} else {
    ||->IoResult<u32>{file.read_le_u32()}
};
for _ in range_step(0u64, path.stat().unwrap().size,4u64){
    v.push(fun().unwrap());
}

还有什么建议吗?这看起来已经好多了。

最佳答案

此解决方案将整个文件读入缓冲区,然后创建缓冲区的单词 View ,然后将这些单词映射到向量中,转换字节顺序。 collect() 避免了增长可变向量的所有重新分配。您还可以 mmap 文件而不是将其读入缓冲区。

use std::io::File;
use std::num::{Int, Num};

fn from_bytes<'a, T: Num>(buf: &'a [u8]) -> &'a [T] {
    unsafe {
        std::mem::transmute(std::raw::Slice {
            data: buf.as_ptr(),
            len: buf.len() / std::mem::size_of::<T>()
        })
    }
}

fn main() {
    let buf = File::open(&Path::new("fid")).read_to_end().unwrap();
    let words: &[u32] = from_bytes(buf.as_slice());
    let big = true;
    let v: Vec<u32> = words.iter().map(if big {
        |&n| { Int::from_be(n) }
    } else {
        |&n| { Int::from_le(n) }
    }).collect();
    println!("{}", v);
}

关于io - 我应该如何阅读有关字节序的文件内容?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26287470/

相关文章:

rust - 如何在Rust(使用serde)中反序列化可选的json参数,该参数可以是字符串或字符串数​​组

rust - Rust溢出时带边界的整数运算

Rust 坚持认为可克隆结构的通用参数也必须实现 Clone

java - 如何用Java读取/写入文件

C# 如何在偏移处写入一个字节?

java - 这两个例子中哪一个是更好的代码设计?

java - 编码风格有问题

c# - 写入内存映射文件比非内存映射文件慢

delphi - 将数据写入I/O地址

c# - 一个方法应该有多少条返回语句?