我正在尝试在下载文件的随机 block 并将它们就地组装的上下文中通过随机访问将字节写入文件。 std::io::Write
似乎仅限于顺序写入,因此我当前使用以下实现,它首先需要下载所有 block ,然后执行大操作 write_all
一旦所有 block 都在内存中。
use rand::prelude::*;
use rand; // 0.7.3
fn download<W: std::io::Write>(writer: &mut W) -> std::io::Result<()>
{
// the size (20) is known
let mut buf = [0u8; 20];
// simulate downloading four 5 byte chunks at random disjoint slices in *buf*
for n in (0..20).step_by(5).collect::<Vec<usize>>().choose_multiple(&mut thread_rng(), 4) {
let n = *n as usize;
let chunk: [u8; 5] = rand::random();
buf[n..n+5].clone_from_slice(&chunk);
}
println!("filled buffer: {:?}", buf);
// finally, do (unbuffered) write
writer.write_all(&buf)?;
Ok(())
}
fn main() -> std::io::Result<()> {
let mut f = std::fs::File::create("foo.txt")?;
download(&mut f)?;
Ok(())
}
对于大文件,我认为此解决方案可能会消耗大量内存,我宁愿将每个 block 直接写入文件中,而无需任何中间缓冲区。我看到有write_at
在文档中,但是这种方法对于unix系统是唯一的吗?我正在寻找通用的解决方案。
直觉上,我希望这样的东西能够工作:
use rand::prelude::*;
use rand; // 0.7.3
fn download<W: std::io::Write>(writer: &mut W) -> std::io::Result<()>
{
// the size (20) is known
writer.reserve(20)?;
// simulate downloading four 5 byte chunks at random disjoint slices in *buf*
for n in (0..20).step_by(5).collect::<Vec<usize>>().choose_multiple(&mut thread_rng(), 4) {
let n = *n as usize;
let chunk: [u8; 5] = rand::random();
writer.write_at(chunk, n)?;
}
Ok(())
}
fn main() -> std::io::Result<()> {
let mut f = std::fs::File::create("foo.txt")?;
download(&mut f)?;
Ok(())
}
是否有专门用于写入随机访问文件输出的方法?我可以使用内存映射文件吗?快速搜索我只能找到 positioned-io crate,已经三年没有更新了。 rust 标准库中有类似这个 crate 的东西吗?
最佳答案
您正在寻找 Seek
。 File
实现 Seek
和Write
所以你只需要绑定(bind) Seek
还有:
use std::io::{Write, Seek, SeekFrom, Result as IoResult};
fn download<W: Write + Seek>(writer: &mut W) -> IoResult<()> { /* ... */ }
现在你可以做writer.seek(SeekFrom::Start(*n as u64 * CHUNK_SIZE))?;
在写出 block 之前。
关于rust - 写入带有偏移量的静态大小文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/73071097/