如何阻止std::filesystem::canonical转网络盘符为UNC路径或恢复盘符?
一、阻止转换:避免使用canonical,改用替代方案
std::filesystem::canonical的设计逻辑就是返回绝对且规范化的真实路径,在Windows环境下会自动将映射的网络盘符解析为对应UNC路径,这是它的固有行为,没有直接参数可禁用该转换。如果要保留盘符格式的路径,可选择以下两种方式:
改用Windows原生API
GetFullPathNameW:该函数能将相对路径转为绝对路径,但会保留网络映射盘符,不会解析为UNC。示例代码:#include <windows.h> #include <string> std::wstring get_full_path_with_drive(const std::wstring& path) { wchar_t buffer[MAX_PATH] = {0}; DWORD len = GetFullPathNameW(path.c_str(), MAX_PATH, buffer, nullptr); if (len == 0 || len > MAX_PATH) { // 处理错误逻辑 return L""; } return std::wstring(buffer); }调用该函数处理
L"W:\\31\\arawat.fielsystem_default_check\\matlab\\check_std\\check_std\\",会返回带W:的绝对路径,不会转为UNC格式。手动规范化路径:如果仅需处理路径中的
.、..等相对元素,可通过std::filesystem::path的make_preferred()方法配合手动逻辑实现,避免触发canonical的UNC解析流程。
二、从UNC路径还原回盘符路径
你之前尝试的WNetGetUniversalName是用于将盘符转成UNC的工具,反过来要把UNC路径还原为盘符,应该使用WNetGetConnection API。该函数可根据UNC路径中的共享名,查找对应的映射盘符。
示例代码:
#include <windows.h> #include <string> #include <filesystem> namespace fs = std::filesystem; std::wstring unc_to_drive_path(const fs::path& unc_path) { if (!unc_path.is_absolute() || !unc_path.has_root_name()) { return unc_path.wstring(); } // 提取UNC路径的服务器+共享名部分,例如"\\bgl-zp31-cifs\\vmgr" std::wstring unc_root = unc_path.root_name().wstring() + L"\\" + unc_path.root_directory().relative_path().wstring(); wchar_t drive_buffer[3] = {0}; // 存储盘符,如"W:" DWORD buffer_len = sizeof(drive_buffer) / sizeof(wchar_t); DWORD result = WNetGetConnectionW(unc_root.c_str(), drive_buffer, &buffer_len); if (result != NO_ERROR) { // 未找到对应映射盘符,返回原UNC路径 return unc_path.wstring(); } // 拼接盘符与剩余路径部分 return drive_buffer + unc_path.relative_path().wstring(); }
调用该函数处理你的UNC路径,即可还原为W:\\31\\arawat.fielsystem_default_check\\matlab\\check_std\\check_std格式的盘符路径。
注意:若该UNC共享未被映射到任何盘符,WNetGetConnection会执行失败,此时只能保留原UNC路径。
内容的提问来源于stack exchange,提问作者Atul Rawat

