命名文件、路径和命名空间

Windows支持的所有文件系统都使用文件和目录的概念来访问磁盘或设备上存储的数据。 Windows处理文件和设备 I/O Windows API 的开发人员应了解文件和目录名称的各种规则、约定和限制。

可以使用文件 I/O API 从磁盘、设备和网络共享访问数据。 文件和目录以及命名空间是路径概念的一部分,该路径是获取数据的字符串表示形式,无论数据是否来自磁盘或设备或特定操作的网络连接。

某些文件系统(如 NTFS)支持链接的文件和目录,它们也遵循文件命名约定和规则,就像常规文件或目录一样。 有关其他信息,请参阅 硬链接和交接点 以及 重新分析点和文件操作

有关其他信息,请参阅以下子部分:

若要了解如何配置Windows 10以支持长文件路径,请参阅最大路径长度限制

文件和目录名称

所有文件系统都遵循单个文件的相同常规命名约定:基本文件名和可选扩展名,用句点分隔。 但是,每个文件系统(如 NTFS、CDFS、exFAT、UDFS、FAT 和 FAT32)可以具有有关目录或文件路径中各个组件形成的具体和不同的规则。 请注意, 目录 只是一个将目录指定为目录的特殊属性的文件,否则必须遵循与常规文件相同的命名规则。 由于术语 目录 仅引用了文件系统相关的特殊类型的文件,因此某些参考资料将使用常规术语 文件 来包含目录和数据文件的概念,例如。 因此,除非另有指定,否则文件的任何命名或用法规则或示例也应应用于目录。 术语 路径 是指一个或多个目录、反斜杠和卷名称。 有关详细信息,请参阅 “路径” 部分。

字符计数限制也可能不同,根据使用的文件系统和路径名称前缀格式而异。 支持向后兼容机制会进一步复杂。 例如,较旧的 MS-DOS FAT 文件系统最多支持基文件名的 8 个字符和扩展名的 3 个字符,总共包含 12 个字符,包括点分隔符。 这通常称为 8.3 文件名。 Windows FAT 和 NTFS 文件系统不限于 8.3 文件名,因为它们具有长文件名支持,但它们仍支持 8.3 版本的长文件名。

命名约定

以下基本规则使应用程序能够创建和处理文件和目录的有效名称,而不考虑文件系统:

  • 使用句点将基文件名与目录或文件名称中的扩展名分隔开来。

  • 使用反斜杠 (\) 分隔路径组件。 反斜杠将文件名从路径中除以,另一个目录名称从路径中的另一个目录名称中除名。 不能对实际文件或目录使用名称中的反斜杠,因为它是将名称分隔为组件的保留字符。

  • 根据需要使用反斜杠作为 卷名称的一部分,例如“C:\”在“C:\path\file”或“\\server\share\path\file”中的“\\server\share\path\file”中,用于通用命名约定 (UNC) 名称。 有关 UNC 名称的详细信息,请参阅 “最大路径长度限制 ”部分。

  • 不要假定区分大小写。 例如,考虑 OSCAR、奥斯卡和奥斯卡的名称相同,即使某些文件系统 ((如符合 POSIX 的文件系统)) 可能将其视为不同。 请注意,NTFS 支持 POSIX 语义以区分大小写,但这不是默认行为。 有关详细信息,请参阅 CreateFile

  • 卷指定符 (驱动器号) 同样不区分大小写。 例如,“D:\”和“d:\”引用同一卷。

  • 将当前代码页中的任何字符用于名称,包括扩展字符集中的 Unicode 字符和字符, (128-255) ,但以下除外:

    • 以下保留字符:

      • <(小于)
      • >(大于)
      • : (冒号)
      • "(双引号)
      • /(正斜杠)
      • \(反斜杠)
      • | (垂直条或管道)
      • ? (问号)
      • *(星号)
    • 整数值零,有时称为 ASCII NUL 字符。

    • 整数表示形式介于 1 到 31 的范围中的字符,但允许这些字符的备用数据流除外。 有关文件流的详细信息,请参阅 文件流

    • 目标文件系统不允许的任何其他字符。

  • 使用句点作为路径中的目录 组件 来表示当前目录,例如“.\temp.txt”。 有关详细信息,请参阅 路径

  • 使用两个连续句点 (。。) 作为表示当前目录父目录的路径中的目录 组件 ,例如“.”。\temp.txt”。 有关详细信息,请参阅 路径

  • 请勿对文件的名称使用以下保留名称:

    CON、PRN、AUX、NUL、COM1、COM2、COM3、COM4、COM5、COM6、COM7、COM8、COM9、LPT1、LPT2、LPT3、LPT4、LPT5、LPT6、LPT7、LPT8 和 LPT9。 此外,请避免这些名称紧跟扩展;例如,不建议NUL.txt。 有关详细信息,请参阅命名空间

  • 不要使用空格或句点结束文件或目录名称。 尽管基础文件系统可能支持此类名称,但Windows shell 和用户界面不支持。 但是,可以接受将句点指定为名称的第一个字符。 例如,“.temp”。

短名称与长名称

长文件名被视为超出短 MS-DOS ((也称为 8.3) 样式命名约定)的任何文件名。 创建长文件名时,Windows还可以创建名称的短 8.3 形式,称为 8.3 别名或短名称,并将其存储在磁盘上。 出于系统范围或指定卷的性能原因,可以禁用此 8.3 别名,具体取决于特定文件系统。

Windows Server 2008、Windows Vista、Windows Server 2003 和 Windows XP:在Windows 7 和 Windows Server 2008 R2 之前,无法为指定卷禁用 8.3 别名。

在许多文件系统上,文件名将包含一个平铺 (~) 名称的每个组件,这些组件太长而不符合 8.3 命名规则。

注意

并非所有文件系统都遵循平铺替换约定,并且系统可以配置为禁用 8.3 别名生成,即使它们通常支持它。 因此,不要假设 8.3 别名已存在于磁盘上。

 

若要从系统请求 8.3 文件名、长文件名或文件的完整路径,请考虑以下选项:

  • 若要获取长文件名的 8.3 格式,请使用 GetShortPathName 函数。
  • 若要获取短名称的长文件名版本,请使用 GetLongPathName 函数。
  • 若要获取文件的完整路径,请使用 GetFullPathName 函数。

在较新的文件系统(如 NTFS、exFAT、UDFS 和 FAT32)上,Windows将长文件名存储在 Unicode 的磁盘上,这意味着始终保留原始的长文件名。 即使长文件名包含扩展字符,也是如此,而不考虑磁盘读取或写入操作期间处于活动状态的代码页。

可以在 NTFS 文件系统分区和 Windows FAT 文件系统分区之间复制使用长文件名的文件,而不会丢失任何文件名信息。 对于较旧的 MS-DOS FAT 和某些类型的 CDFS (CD-ROM) 文件系统来说,这可能不是事实,具体取决于实际文件名。 在这种情况下,如果可能,将替换短文件名。

路径

指定文件 的路径 由一个或多个 组件组成,由特殊字符分隔, (反斜杠) ,每个组件通常是目录名或文件名,但下面讨论了一些值得注意的异常。 对于系统对路径的开头或 前缀的解释通常至关重要。 此前缀确定路径正在使用的 命名空间 ,以及用于路径中哪个位置(包括最后一个字符)的特殊字符。

如果路径的组件是文件名,则它必须是最后一个组件。

路径的每个组件也将受到为特定文件系统指定的最大长度的约束。 通常,这些规则分为两个类别: 。 请注意,目录名称由文件系统存储为特殊类型的文件,但文件的命名规则也适用于目录名称。 总之,路径只是特定文件或目录名称存在的所有目录之间的层次结构的字符串表示形式。

完全限定与相对路径

对于操作文件的 Windows API 函数,文件名通常相对于当前目录,而某些 API 需要完全限定的路径。 文件名相对于当前目录(如果文件名不以下列项之一开头):

  • 任何格式的 UNC 名称,始终以两个反斜杠字符开头, (“\\”) 。 有关更多信息,请参见下一节。
  • 带反斜杠的磁盘设计器,例如“C:\”或“d:\”。
  • 单个反斜杠,例如“\directory”或“\file.txt”。 这也称为 绝对路径

如果文件名仅以磁盘指示符开头,但不以冒号后反斜杠开头,则会将其解释为具有指定字母的驱动器上当前目录的相对路径。 请注意,当前目录可能不是根目录,具体取决于它在磁盘上最近的“更改目录”操作期间设置的内容。 此格式的示例如下所示:

  • “C:tmp.txt”是指驱动器 C 上当前目录中名为“tmp.txt”的文件。
  • “C:tempdir\tmp.txt”是指驱动器 C 上的当前目录的子目录中的文件。

如果路径包含“双点”,则表示路径是相对路径:即路径的一个组件中的两个句点。 此特殊说明符用于表示当前目录上方的目录,否则称为“父目录”。 此格式的示例如下所示:

  • "..\tmp.txt“指定位于当前目录父目录中的名为tmp.txt的文件。
  • "..\..\tmp.txt“指定一个文件,该文件是当前目录上方的两个目录。
  • "..\tempdir\tmp.txt“指定一个名为tmp.txt的文件,该文件位于名为 tempdir 的目录中,该文件是当前目录的对等目录。

相对路径可以合并这两个示例类型,例如“C:..\tmp.txt”。 这很有用,因为尽管系统跟踪当前驱动器以及该驱动器的当前目录,但如果系统具有多个) ,无论哪个驱动器指示符设置为当前驱动器,它也会跟踪每个不同驱动器号中的当前目录 (。

最大路径长度限制

在Windows 10版本 1607 之前的Windows版本中,路径的最大长度为MAX_PATH,定义为 260 个字符。 在更高版本的Windows中,需要更改注册表项或使用 组策略 工具来删除限制。 有关完整详细信息,请参阅 最大路径长度限制

命名空间

Windows API 中使用的命名空间约定有两个主要类别,通常称为 NT 命名空间Win32 命名空间。 NT 命名空间设计为其他子系统和命名空间可以存在的最低级别命名空间,包括 Win32 子系统和 Win32 命名空间(按扩展)。 POSIX 是基于 NT 命名空间构建Windows中的子系统的另一个示例。 早期版本的Windows还定义了某些特殊设备(如通信 (串行和并行) 端口)的名称,以及默认显示控制台作为现在称为 NT 设备命名空间的一部分,在当前版本的Windows中仍受支持,以实现向后兼容性。

Win32 文件命名空间

本部分和以下部分汇总了 Win32 命名空间前缀和约定,其中介绍了如何使用它们。 请注意,这些示例旨在与 Windows API 函数一起使用,并不一定使用 Windows shell 应用程序(如 Windows Explorer)。 因此,可能的路径范围比通常从 Windows shell 应用程序提供的路径范围要大,Windows利用此路径的应用程序可以使用这些命名空间约定进行开发。

对于文件 I/O,路径字符串的“\\?\”前缀告知Windows API 禁用所有字符串分析,并将后面的字符串直接发送到文件系统。 例如,如果文件系统支持大型路径和文件名,则可以超过由Windows API 强制实施的MAX_PATH限制。 有关常规最大路径限制的详细信息,请参阅上一部分 最大路径长度限制

由于它关闭了路径字符串的自动扩展,因此“\\?\”前缀还允许在路径名称中使用“..”和“.”,如果在尝试对这些文件执行操作时,如果尝试对这些文件执行操作,否则保留的相对路径说明符作为完全限定路径的一部分,这很有用。

许多但并非所有文件 I/O API 都支持“\\?\”;应查看每个 API 的参考主题以确保。

请注意,应使用 Unicode API 来确保“\\?\”前缀允许超过 MAX_PATH

Win32 设备命名空间

“\\.\”前缀将访问 Win32 设备命名空间,而不是 Win32 文件命名空间。 这是直接访问物理磁盘和卷的方式,而无需通过文件系统(如果 API 支持这种类型的访问)。 可以使用 CreateFileDefineDosDevice 函数(例如 () )以这种方式访问磁盘以外的许多设备。

例如,如果要打开系统的串行通信端口 1,则可以在调用 CreateFile 函数时使用“COM1”。 这很有效,因为 COM1-COM9 是 NT 命名空间中保留名称的一部分,尽管使用“\\.\”前缀也会使用这些设备名称。 相比之下,如果安装了 100 个端口串行扩展板并且想要打开 COM56,则无法使用“COM56”打开它,因为 COM56 没有预定义的 NT 命名空间。 需要使用“\\.\COM56”打开它,因为“\\.\”直接转到设备命名空间,而无需尝试找到预定义的别名。

使用 Win32 设备命名空间的另一个示例是将 CreateFile 函数与“\.\PhysicalDriveX”配合使用 (其中 X 是有效的整数值) 或“\\.\CdRomX”。 这样,就可以直接访问这些设备,绕过文件系统。 这很有效,因为这些设备名称由系统创建,因为这些设备被枚举,并且某些驱动程序还会在系统中创建其他别名。 例如,实现名称“C:\”的设备驱动程序有自己的命名空间,也恰好是文件系统。

通过 CreateFile 函数的 API 通常使用“\\.\”前缀,因为 CreateFile 是用于打开文件和设备的函数,具体取决于所使用的参数。

如果使用的是 Windows API 函数,则应使用“\\.\”前缀仅访问设备,而不是文件。

大多数 API 不支持“\\.\”;只有那些设计用于处理设备命名空间的人才能识别它。 请始终检查每个 API 的参考主题以确保。

NT 命名空间

还有一些 API 允许使用 NT 命名空间约定,但大多数情况下,Windows对象管理器会使这一点变得不必要。 为了说明,使用 Windows Sysinternals WinObj 工具在系统对象浏览器中浏览Windows命名空间非常有用。 运行此工具时,看到的是从根目录开始的 NT 命名空间或“\”。 名为“Global??”的子文件夹是 Win32 命名空间所在的位置。 命名设备对象驻留在“Device”子目录中的 NT 命名空间中。 在这里,还可以找到 Serial0 和 Serial1(如果系统上存在)表示前两个 COM 端口的设备对象。 表示卷的设备对象类似于“HarddiskVolume1”,尽管数字后缀可能有所不同。 子目录“Harddisk0”下的名称“DR0”是表示磁盘的设备对象的示例,等等。

若要使这些设备对象可由Windows应用程序访问,设备驱动程序会在 Win32 命名空间“Global??”中创建符号链接 (符号链接) 到其各自的设备对象。 例如,“Global??”子目录下的 COM0 和 COM1 只是与 Serial0 和 Serial1 的符号链接,“C:”是与 HarddiskVolume1 的符号链接,“Physicaldrive0”是 DR0 的符号链接,依此而论。 如果没有符号链接,指定的设备“Xxx”将无法使用 Win32 命名空间约定的任何Windows应用程序,如前所述。 但是,可以使用支持 NT 命名空间绝对路径格式“\Device\Xxx”的任何 API 打开句柄。

通过终端服务和虚拟机添加多用户支持后,还需要在 Win32 命名空间中虚拟化系统范围的根设备。 这是通过将名为“GLOBALROOT”的符号链接添加到 Win32 命名空间来实现的,可以在前面讨论的 WinObj 浏览器工具的“Global??”子目录中看到该链接,并且可以通过路径“\\?\GLOBALROOT”进行访问。 此前缀可确保其后面的路径位于系统对象管理器的真实根路径中,而不是依赖于会话的路径。

文件系统功能比较