首页 > 解决方案 > 在运行时加载资源文件

问题描述

假设我有这个架构:

.
├── Cargo.lock
├── Cargo.toml
├── src/
│   ├── main.rs
├── rsc/
│   ├── file.xml

我想file.xml在每次运行时加载以填充一些表。为此,我可以写:

use std::fs::File;
use std::path::Path;

fn open<P: AsRef<Path>>(path: P) {
    let _ = File::open(path).unwrap();
    println!("file opened");
}

fn main() {
    open("../rsc/file.xml");
}

但是如果我不从src.

我可以执行以下操作:

fn main() {
    include_str!("../rsc/file.xml");
}

但这将在编译时完成,这意味着更改file.xml意味着重新编译程序,因此在可维护性方面完全不安全。

我可以看到的另一个选项是将rsc路径作为参数提供给我的程序,但我发现它有点麻烦,因为这不是一个可选参数,我真的需要知道我的rsc目录在哪里,而且我知道我的 crate 将具有这种架构。

有什么我看不到的吗?

我看到了这篇文章:如何避免 Rust 中的硬编码值

但我的问题总结在这一部分:

如果您正在部署二进制文件,您可能必须提供一条路径,让您的应用程序可以找到其资源。

并且没有其他的精确度。

标签: filerust

解决方案


您可以使用std::env::current_exe()找到二进制文件的路径。您可以使用它来查找二进制文件所在的目录,然后使用它来加载与该目录相关的一些资源。

例如,如果您的资源位于与二进制文件位于同一目录中的目录“rsrc”中:

let mut rsrc_dir = std::env::current_exe()
    .expect("Can't find path to executable");

// Directory containing binary
rsrc_dir.pop();

// Subdir relative to binary
rsrc_dir.push("rsrc");

仅当您的二进制文件与它的资源文件一起安装在相对于二进制文件的某个固定位置时,这才有用。请记住,大多数用户不会从 github 克隆您的 crate 并以这种方式运行它 - 典型的安装方法包括:

  • 安装它cargo install
  • 使用一些特定于操作系统的包管理器
  • 也许下载一个 tar 或 zip 文件并解压缩它

似乎cargo install目前不处理安装关联的资源文件(尽管有一个开放的错误)。


推荐阅读