Skip to content

Ch 18: OsStr与OsString

OsStr和OsString是Rust中用于处理操作系统相关字符串的类型。普通&str/String假设字符串是有效的UTF-8,但操作系统并不总是这样认为:

  • Windows文件名:可以是非UTF-8编码(取决于系统代码页)
  • Unix文件名:可以是任何字节序列(除/和\0)

OsStr/OsString提供了一种跨平台的方式处理这些字符串。

use std::ffi::{OsStr, OsString};
fn main() {
// OsStr 是系统字符串的引用
let os_str: &OsStr = OsStr::new("hello");
println!("OsStr: {:?}", os_str);
// OsString 是可变的、拥有的系统字符串
let mut os_string = OsString::from("world");
os_string.push("!");
println!("OsString: {:?}", os_string);
}
use std::ffi::{OsStr, OsString};
fn main() {
// OsStr::new 从 &str 创建(总是有效)
let os_str: &OsStr = OsStr::new("hello");
println!("OsStr from str: {:?}", os_str);
// OsString::from 从 &str 创建
let os_string: OsString = OsString::from("world");
println!("OsString from str: {:?}", os_string);
// to_os_string 转换
let os_string2 = os_str.to_os_string();
println!("to_os_string: {:?}", os_string2);
}
use std::ffi::{OsStr, OsString};
use std::os::unix::ffi::OsStringExt;
fn main() {
// Unix上可以从原始字节创建OsString
let bytes: Vec<u8> = vec![104, 101, 108, 108, 111]; // "hello"
let os_string = OsString::from_vec(bytes);
println!("OsString from bytes: {:?}", os_string);
// 转为字节
let back_to_bytes: Vec<u8> = os_string.into_vec();
println!("Back to bytes: {:?}", back_to_bytes);
}
use std::ffi::{OsStr, OsString};
fn main() {
let os_str: &OsStr = OsStr::new("hello world");
// is_empty 检查是否为空
println!("is_empty: {}", os_str.is_empty());
// len 返回字节长度
println!("len: {}", os_str.len());
// 迭代(Unix上是字节,Windows上是WChars)
for b in os_str.bytes() {
print!("{} ", b);
}
println!();
}
use std::ffi::OsString;
use std::path::PathBuf;
fn main() {
// PathBuf 实现了 From<OsString>
let os_string = OsString::from("/home/user/file.txt");
let path_buf: PathBuf = os_string.into();
println!("PathBuf: {:?}", path_buf);
// PathBuf 可以转为 OsString
let os_str = path_buf.as_os_str();
println!("As OsStr: {:?}", os_str);
}
use std::ffi::{OsStr, OsString};
fn main() {
// Unix上 OsStr 包含原始字节
let os_str: &OsStr = OsStr::new("hello");
// to_str 可能失败(非UTF-8)
if let Some(s) = os_str.to_str() {
println!("to_str: {}", s);
} else {
println!("不是有效的UTF-8");
}
// to_string_lossy 用�替换无效字符
let lossy = os_str.to_string_lossy();
println!("lossy: {}", lossy);
}
use std::ffi::{OsStr, OsString};
use std::process;
fn main() {
// 环境变量使用OsStr
let path_var = std::env::var_os("PATH");
if let Some(path) = path_var {
println!("PATH exists, len: {}", path.len());
// 迭代路径
for p in std::env::split_paths(&path) {
println!(" {}", p.display());
}
}
// 获取单个环境变量
if let Some(home) = std::env::var_os("HOME") {
println!("HOME: {:?}", home);
}
}
方法说明
new(s)从&str创建OsStr
to_os_string()转为OsString
to_str()转为Option
to_string_lossy()转为String,替换无效字符
is_empty()是否为空
len()字节长度
bytes()字节迭代器
方法说明
from(s)从&str创建
new()创建空OsString
push()追加
pop()移除最后部分
clear()清空
into_string()尝试转为String
into_vec()Unix上转为Vec
use std::ffi::OsString;
fn main() {
// std::env::args() 返回 OsString 迭代器
for arg in std::env::args() {
println!("arg: {:?}", arg);
}
// args_os() 返回 OsString 版本
for arg in std::env::args_os() {
println!("arg_os: {:?}", arg);
}
}
use std::ffi::OsString;
use std::fs;
use std::path::PathBuf;
fn main() -> std::io::Result<()> {
// 读取目录,文件名是OsString
for entry in fs::read_dir(".")? {
let entry = entry?;
let file_name: OsString = entry.file_name();
println!("file: {:?}", file_name);
// 可能不是有效UTF-8
if let Some(name) = file_name.to_str() {
println!(" as str: {}", name);
}
}
Ok(())
}
  1. 非UTF-8处理:OsStr/OsString可以包含无效UTF-8数据
  2. 跨平台差异:Unix上是字节序列,Windows上是WCHAR序列
  3. 优先使用Path:处理文件路径时优先使用Path/PathBuf,它们实现了AsRef<OsStr>
  4. 避免频繁转换:to_str/to_string_lossy可能失败,避免在热路径中频繁调用

今天我们学习了OsStr和OsString:

  1. 设计目的 - 处理操作系统相关的非UTF-8字符串
  2. OsStr - 系统字符串的引用
  3. OsString - 可变的、拥有的系统字符串
  4. 转换方法 - to_str()、to_string_lossy()
  5. 跨平台 - Unix处理字节,Windows处理WCHAR

在处理文件路径、环境变量等系统相关字符串时,使用OsStr/OsString可以确保跨平台兼容性。