Io 我应该如何读取有关endianess的文件内容?

Io 我应该如何读取有关endianess的文件内容?,io,coding-style,rust,endianness,idioms,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(); 但就我所知,我将不得不这样做(简化): 但这太难看了,我只是想知道是否有更好的方法来做

我可以看到,在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![];
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());
}

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

此解决方案将整个文件读入一个缓冲区,然后创建一个作为字的缓冲区视图,然后将这些字映射到一个向量,转换endianness
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);
}
使用std::io::File;
使用std::num::{Int,num};
fn来自_字节和'a[T]{
不安全{
std::mem::transmute(std::raw::Slice{
数据:buf.as_ptr(),
len:buf.len()/std::mem::size\u of::()
})
}
}
fn main(){
让buf=File::open(&Path::new(“fid”))。读取到结尾()。展开();
let words:&[u32]=来自_字节(buf.as_slice());
让大=真;
设v:Vec=words.iter().map(如果较大{
|&n{Int::from_be(n)}
}否则{
|&n{Int::from_le(n)}
}).收集();
println!(“{}”,v);
}

它并没有那么难看。如果你想看到丑陋的ParrotVM下载源代码,并认真地看我在C中所做的事情:),如果你不想看的话,就把它抽象掉吧。我透明地检测字节顺序的方法是在文件头存储一个幻数(如1234),并在运行时使用它来检测字节顺序。就原始人而言,显然锈已经提供了它们。(文件::read_be_u32等)为了提高效率,您需要将分支从循环中提升出来—可能一直提升到模板参数。
gold
链接器完成了这项工作,它非常庞大。@codenheim:U+FEFF是标准BOM,在这种情况下,在我看来是一个不错的选择。@ChrisMorgan-对于字符数据,当然,这是一个很好的观点。旧习难改。2001年,当我开始这项工作时,我对Unicode的知识是零。虽然这不仅仅是字符数据,但它在标题中包含了比字节顺序更多的信息。在当前格式中,它实际上已简化为0或1。我的目标是使用一种在以各种方式交换时可以识别的位模式。我明白为什么现在这是一个糟糕的选择,为什么FEFF是一个好的选择。
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());
}
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);
}