这是一个在 Windows 10 下使用中文、日文等双字节字符路径映射网络驱动器时发生的经典问题。你遇到的“截断”现象,表面上看着像是字符被切掉了一半,实际原因是 Windows 内部处理编码时的字符集转换错位。
下面从机制到解决,分步说明。
Windows 内核中的所有字符串其实都是 UTF-16 存储的,理论上完全支持中文。但问题出在旧版 API 的 ANSI 封装层。
映射网络驱动器这一功能,底层走的是 WNetAddConnection 系列 API。这个 API 有两个版本:
- Wide 版本(
WNetAddConnectionW):使用 UTF-16,没问题。 - ANSI 版本(
WNetAddConnectionA):需要先把字符串转换成 系统 ANSI 代码页(例如中文的 GBK,日文的 Shift-JIS)。
如果代码页转换失败,或调用方使用了错误的代码页,就会出现字符丢失、乱码、截断。
更复杂的是:不同的调用入口,走的是不同的代码页。
| 调用入口 | 实际使用的代码页 | 结果 | |---------|----------------|------| | 资源管理器“映射网络驱动器”对话框 | ANSI 代码页(CP936/CP932) | 中文路径通常会出错 | | net use 命令行(Windows 10 1803 之前) | OEM 代码页(通常是 CP936,但对某些字符集可能不同) | 不同代码页会导致不一致 | | PowerShell 的 New-PSDrive -Persist | Unicode(直接走 Wide API) | 正常 | | subst 命令 | Unicode | 正常 |
所以在 Win10 上会出现一种常见现象:
用
net use能成功,但在资源管理器里看是乱的; 或者在资源管理器里输入中文路径,直接被截断成半个字。
2. 为什么只有中文/日文会这样?
因为单字节字符(如英文、数字)在 ANSI 和 Unicode 下的映射是完全一致的,没有任何转换损失。
双字节字符则不同:
- 中文在 GBK 中占 2 字节,在 UTF-16 中占 2 字节,但内部编码规则完全不同。
- 某些中文的 GBK 编码恰好落在 Unicode 的 ASCII 范围之外,转换时一旦代码页判断错误,就会产生“半个字符”的现象。
- 更麻烦的是,Windows 的 OEM 代码页(用于控制台)与 ANSI 代码页(用于 GUI)并不总是相同的,字符映射结果也因此不同。
比如“区块链”这个路径,在 GBK 下是 BF B8 C7 F8 BF E9,但如果你用日文 Shift-JIS 代码页去解析,就会变成完全不相干的字符,甚至产生非法字节序列。
3. 为什么 `subst` 和 PowerShell 没这个问题?
subst 和 New-PSDrive -Persist 在 Windows 10 上直接调用 Unicode 版本的 API,没有经过 ANSI 代码页转换层,因此天然规避了这个问题。
而 net use 在 Windows 10 1803 版之后也切换到了 Unicode 版本,但前提是你使用的是内置的 net.exe。如果你的脚本调用了旧版 API,或者你在某些命令工具(如 CMD 的 pushd)中通过 ANSI 环境变量传递路径,依然会触发问题。
4. 解决方案
方案一:使用 `subst`(推荐,最简单)
如果你只是想把一个本地目录映射成盘符:
subst Z: "D:\中文路径\项目"
如果要断开:
subst Z: /D
subst 在 Windows 10 下完全支持中文路径,不存在截断问题。但注意:subst 映射的盘符只对当前用户和当前会话有效,重启后需要重新执行(可以放入启动脚本)。
方案二:使用 PowerShell 的 `New-PSDrive -Persist`
如果你想映射 SMB 网络共享:
New-PSDrive -Name "Z" -PSProvider FileSystem -Root "\\服务器\中文共享" -Persist
-Persist 参数会让它像 net use 一样持久化,重启后依然存在。
方案三:修改 `net use` 的调用方式
如果你必须用 net use,可以先 chcp 65001 切换控制台到 UTF-8(需确认终端本身支持),然后再执行:
chcp 65001
net use Z: "\\服务器\中文共享" /persistent:yes
注意:这种方法在某些版本上依然不可靠,因为 chcp 65001 只影响控制台的代码页,API 内部可能仍然使用系统 ANSI 代码页。
方案四:把系统区域设置改为“Beta: 使用 Unicode UTF-8 提供全球语言支持”
在 设置 → 时间和语言 → 语言 → 管理语言设置 → 更改系统区域设置 中,勾选 “Beta: 使用 Unicode UTF-8 提供全球语言支持”,然后重启。
这会强制所有 ANSI API 使用 UTF-8 作为系统代码页,从而避免双字节截断。
但强烈不推荐:这会影响所有使用 ANSI API 的旧软件,可能引发其他兼容性问题(例如某些老款游戏、金融软件乱码)。
5. 总结
| 原因 | 说明 | |------|------| | ANSI API 的代码页转换层 | 旧版 WNetAddConnectionA 在转换中文时不安全 | | 多编码混用 | 控制台用 OEM,GUI 用 ANSI,两边可能不一致 | | 调用方不同 | net use(旧版)、资源管理器、PowerShell 的结果各不相同 |
最大概率的解决方式:
- 本地路径用
subst - 网络路径用
New-PSDrive -Persist - 不要使用
net use加中文路径(除非你能确保它是 Unicode 版本且在纯 UTF-8 环境下)
如果你遇到的是“资源管理器中输入正常,但映射出来的盘符路径不对”的情况,请先检查是否用了 net use,换成 PowerShell 方案即可稳定解决。