我有一些带有俄语(西里尔字母)名称的文件。
当我在 Windows 资源管理器中打开它们时,名称显示正确。
当我在命令 shell (cmd) 中列出它们时,它们显示为“??????”字符。
有没有办法知道文件名使用了什么编码?
其中一个代码页?(我尝试使用chcp
命令来查找常见的西里尔代码页 866 和 1251,但没有成功)。Unicode(我尝试了 65001,但没有成功)?还有其他吗?
我并不特别关心答案的方法(以下所有方法都可以接受:免费软件程序、Perl 脚本、Powershell 脚本、让我上传文件的网页)。
系统:Windows XP SP3。
答案1
文件名编码由文件系统定义。NTFS 使用 UTF-16。不过这并不重要。
当您dir
在命令行中时,它不会只是盲目地复制字节。它首先必须调用适当的操作系统函数来列出目录,然后将收到的文件详细信息打印到控制台。
当cmd
调用系统函数来检索目录列表时,它已经期望它以首选编码返回(这不一定是您选择的编码 - 稍后会详细介绍)。它不关心 FS 内部使用什么编码,因为 OS 提供了额外的抽象层来简化事情。FS 可以使用您能想到的任何编码,但只要 OS 支持它,cmd
就会以其首选编码而不是 FS 的编码接收文件名。
我提到的“首选编码”是应用了代码页的 ANSI 或 Unicode。在 Windows 2000 之前,ANSI 是默认编码。Windows 2000 及更新版本默认使用 Unicode,但仍可以运行 ANSI 程序。
对于 Unicode 程序,代码页会被完全忽略,并且chcp
不会产生任何影响。它仅用于依赖于正确设置代码页的较旧的 ANSI 程序。对于 Unicode 来说,它不再重要,因为它定义明确,并且支持任何合理程序可以输出的所有内容。
cmd
确实支持 Unicode,因此它将接收已经是 Unicode 的文件名。
正如您已经发现的那样,罪魁祸首是默认字体。这个问题在chcp 上的 Technet 页面:
在使用 Raster 字体的命令提示符窗口中,只有随 Windows XP 安装的原始设备制造商 (OEM) 代码页才能正确显示。其他代码页可在全屏模式或使用 TrueType 字体的命令提示符窗口中正确显示。