【发布时间】:2014-12-04 22:01:45
【问题描述】:
我可以看到,在 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());
}
还有什么建议吗?这已经看起来好多了。
【问题讨论】:
-
这不是那丑。如果你想看丑陋的下载 Parrot VM 源代码并看看我必须在 C 中做什么。:) 说真的,如果你不想看它,就把它抽象掉。我透明地检测字节顺序的方法是在文件头存储一个幻数(如 1234),并在运行时使用它来检测字节顺序。至于原语,显然 Rust 已经提供了它们。 (文件::read_be_u32等)
-
为了提高效率,您可能希望将分支提升出循环 - 可能一直到模板参数。
gold链接器做到了这一点,它是巨大的。 -
@codenheim:U+FEFF 是标准 BOM,在这种情况下对我来说是个不错的选择。
-
@ChrisMorgan - 对于字符数据,当然,好点。旧习难改。 2001 年我开始这项工作时,我对 Unicode 的了解为零。虽然这不仅仅是字符数据,但它在标题中包含了比字节顺序更多的信息。它现在实际上已简化为当前格式的 0 或 1。我的目标是使用一种在以各种方式交换时可识别的位模式。我明白为什么现在它是一个糟糕的选择,以及为什么 FEFF 是一个好的选择。
标签: io coding-style rust endianness idioms