http - 如何告诉 Rust 中的 std::io::copy 停止读取并完成写入?
问题描述
我正在通过 Rust 直接下载 MP3 音频流。由于这个流是不确定的,我希望能够提前取消它以保存我到目前为止下载的内容。目前,我通过按 CTRL + C 来停止程序。这会生成一个 stream.mp3 文件,然后我可以播放和收听,虽然这可行,但并不理想。
给定以下代码,我如何以编程方式io::copy()
提前停止并让它保存文件而不杀死整个程序?
extern crate reqwest;
use std::io;
use std::fs::File;
// Note that this is a direct link to the stream, not a webpage with HTML and a stream
const STREAM_URL: &str = "http://path.to/stream";
fn main() {
let mut response = reqwest::get(STREAM_URL)
.expect("Failed to request mp3 stream");
let mut output = File::create("stream.mp3")
.expect("Failed to create file!");
io::copy(&mut response, &mut output)
.expect("Failed to copy mp3 stream to file");
}
解决方案
正如评论所说,io::copy
这是一个方便的功能,可以Reader
完整地阅读 a 并将其内容写入 aWriter
而不会在两者之间停下来;它用于当您不关心中间状态而只想将整个事物从阅读器运送到作者时。
如果您只想要 的前几个 Kb,则response
可以使用io::Read::take,它将 限制为Reader
您指定的任何限制。它将返回一个新的Reader
,您可以将其传递给io::copy
.
是的,您可以在任意位置剪切 MP3 文件。它是一种帧格式,虽然您很可能会破坏最后一帧,但实际上所有 mp3 解码器都能够处理这种情况。
一些合乎情调的东西
// `Read` needs to be in scope, so .take() is available on a `io::Read`
use std::io::Read;
use std::io;
use std::fs::File;
fn main() {
let mut response = reqwest::get(STREAM_URL)
.expect("Failed to request mp3 stream")
.take(100*1024); // Since `Response` is `Read`, we can `take` from it.
let mut output = File::create("stream.mp3")
.expect("Failed to create file!");
// `response` is a limited reader, so it will only read 100kb before
// returning EOF, signaling a successful completion to `copy`.
io::copy(&mut response, &mut output)
.expect("Failed to copy mp3 stream to file");
}
推荐阅读
- bash - bash if 语句二元运算符
- bot-framework-composer - 如何在 Bot-Framework-Composer V 2.1.1 中添加翻译中间件
- angular - Angular——处理页面刷新
- google-places-api - Google Place API 限制为 5 条评论
- ruby-on-rails - 带有accepts_nested_attributes_for 和belongs_to 的Rails 嵌套表单
- ibm-cloud - IBM Cloud Container Registry:如何使用 CLI 删除一组(甚至全部)映像
- r - For循环将因子变量中的NA转换为“无”
- chocolatey - 在 Chocolatey 中填充一个 .bat 文件
- python - 将 JSON 转换为全表
- c++ - SDL2:SDL 函数 SDL_Delay() 在使用 SDL_QUIT 退出程序时冻结程序