You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何以跨平台方式序列化Rust中的OsString?

跨平台序列化任意文件路径的方案

我尝试将文件路径存储到文件中,这些路径以PathBuf值的形式传入。遗憾的是,PathBuf无法直接转换为字节切片,它可以转换为OsString,但仍存在将该字符串写入文件的问题。

虽然有into_encoded_bytes()方法及其对应的不安全from_encoded_bytes_unchecked()方法,但安全说明指出,它们仅适用于同一平台同一Rust版本编码的数据,无法满足跨平台迁移数据文件或更新程序的需求。

from_encoded_bytes_unchecked()方法还链接到模块级别的编码转换讨论,其中描述了Windows、Unix和“其他平台”各自的编码方式,但“所有平台”部分仅指向into_encoded_bytes()和from_encoded_bytes_unchecked()方法,这些方法不支持在与写入时不同的平台读取数据。

除了尝试转换为String且在非有效UTF-8时拒绝处理之外,是否存在任意文件路径的跨平台序列化方案?


可行的跨平台序列化方案

1. 使用serde + serde_with快速实现

serde_with库提供了对OsString和PathBuf的跨平台序列化支持,底层基于WTF-8编码转换,能兼容所有平台的路径格式,无需手动处理编码细节。

首先添加依赖:

[dependencies]
serde = { version = "1.0", features = ["derive"] }
serde_with = "3.0"
serde_json = "1.0" # 可替换为bincode、yaml-rust等其他序列化格式

示例代码:

use serde::{Deserialize, Serialize};
use serde_with::serde_as;
use std::path::PathBuf;

// 使用serde_as宏为PathBuf指定跨平台序列化方式
#[serde_as]
#[derive(Serialize, Deserialize, Debug)]
struct AppData {
    #[serde_as(as = "serde_with::rust::OsString")]
    config_path: PathBuf,
}

fn main() {
    // 构造包含任意路径的实例(包括非UTF-8路径)
    let app_data = AppData {
        config_path: PathBuf::from("/user/docs/测试文件\x80"),
    };

    // 序列化为JSON字符串
    let serialized = serde_json::to_string(&app_data).unwrap();
    println!("序列化结果:{}", serialized);

    // 跨平台反序列化
    let deserialized: AppData = serde_json::from_str(&serialized).unwrap();
    println!("反序列化结果:{:?}", deserialized.config_path);
}

2. 手动使用os_str_bytes库处理编码

如果不需要完整的serde序列化框架,可以直接使用os_str_bytes库,它提供了OsString与WTF-8编码字符串的双向转换,WTF-8是一种兼容UTF-8的编码,能表示所有平台的OsString内容。

添加依赖:

[dependencies]
os_str_bytes = "6.0"

示例代码:

use os_str_bytes::OsStringExt;
use std::ffi::OsString;
use std::path::PathBuf;

// 将PathBuf序列化为跨平台兼容的字符串
fn serialize_path(path: &PathBuf) -> String {
    path.as_os_str().encode_wtf8()
}

// 将字符串反序列化为PathBuf
fn deserialize_path(serialized: &str) -> PathBuf {
    OsString::decode_wtf8(serialized)
        .expect("无效的路径编码")
        .into()
}

fn main() {
    let original_path = PathBuf::from("C:\\用户\\文档\\特殊路径\x80");
    let serialized_str = serialize_path(&original_path);
    let restored_path = deserialize_path(&serialized_str);

    assert_eq!(original_path, restored_path);
}

方案说明

  • WTF-8编码是跨平台的,它可以正确表示Windows的UTF-16路径(包括代理对)和Unix的任意字节路径,序列化后的字符串可安全存储或传输。
  • 上述方案不依赖特定平台或Rust版本,满足跨平台迁移数据和程序更新的需求。
  • 既避免了into_encoded_bytes()的平台绑定限制,也不会拒绝非UTF-8格式的路径。

内容的提问来源于stack exchange,提问作者Nick

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.14 14:29:57