我正在尝试将原始操作系统文件名保存到存储中,因此我需要获取rdd.map
的原始字节。
似乎可以在* nix平台上调用as_bytes()
,但这不是在MS Windows上定义的。
是否有可移植的方式将OsStr
转换为字节?
答案 0 :(得分:3)
在Rust 1.16中,没有用于在Windows上获取OsStr
的字节的已定义接口。 OsStr
delegates to system-specific code的实际实施情况。在* nix上,这是wrapper around a Vec<u8>
;在Windows上,这是wrapper around a Wtf8Buf
。使用Wtf8Buf
实现Vec<u8>
时,不会公开该实现细节。有关WTF-8的更多细节可用on its website,其中包括此引用,强调我的:
在Windows上(在其API中使用可能格式错误的UTF-16), Rust标准库在内部使用WTF-8作为操作系统字符串,但确实如此 不暴露WTF-8字节序列。
“问题”是在不同的平台上,在将其传递给操作系统界面时,没有统一的“字符串”概念。在* nix上,通常接口接受几乎之类的东西,如UTF-8,除非它们不处理嵌入的NUL值。在Windows上,这取决于您是否正在调用API的W
或A
变体,尽管W
变体是首选。
这变得更加困难,因为库也可能使用来自操作系统的不同编码。如果你使用在Windows上* nix上创建的C库,尤其如此 - 它几乎可以保证接受伪UTF-8字符串,然后进行某种有损转换以调用正确的底层API。
Rust通过提供不透明类型OsStr
和OsString
来避免这一切。
如果您需要将OsStr
传递给接受UTF-8数据的函数,则需要将其转换为String
或&str
,然后您才能获得字节那。如果需要将其传递给接受LPCWSTR
的函数,首先需要转换为Vec<u16>
,然后将指向该缓冲区的指针传递给Windows API。您可以看到an example of how Rust itself does this。
答案 1 :(得分:2)
OsStr
的要点是它的表示是特定于操作系统的。由于技术原因,实现有些复杂(@Shepmaster's answer提供了更多详细信息),但您可以这样想:
OsStr
归结为&[u8]
,因为POSIX函数接受并返回字节字符串; OsStr
可以被认为是&[u16]
,因为Win32 Unicode函数接受并将字符串作为16位单元的数组返回。由于本机Windows API接受16位&#34;宽字符&#34; 1 的序列,因此OsStr
旨在存储。OsStr
。虽然OsStr
可以转换为字节,因为任何东西都可以转换为字节,但这种表示没有用,因为这些字节对用户和系统都没有意义。这就是OsStr::encode_wide()
没有提供在Windows上以字节形式检索内容的方法的原因。但是,它确实提供了u16
迭代在Win32中 有用的基础OsString::from_wide()
值。在另一个方向,OsString
可用于从u16
个值中创建OsStr
。
由您决定持久层如何处理平台之间的这种差异。 Rust enum OsString { Unix(Vec<u8>), Windows(Vec<u16>) }
提供的是实施往返的必要工具,但代码在平台之间必然会有所不同。例如,serde将effectively treating的差异解析为u16
。
<小时/> 1 Windows宽字符字符串有时被描述为UTF-16,因为它是在更高级别解释它们的方式,但这对于所有 OS字符串不正确。 Windows文件名可以包含不有效UTF-16的
full_day
个值对,并且仍然可用。这就是为什么不可能通过例如将Windows字符串表示为字节的原因。将它们转换为UTF-8。