求Windows下获取文件真实大小写敏感路径的函数(游戏Lua绑定场景)
实现Windows下路径大小写敏感验证的方案
要让Windows环境下的文件操作和Linux保持一致的大小写敏感性,核心是获取文件系统中存储的真实路径大小写形式,再与用户输入的路径对比——若不匹配则拒绝操作。以下是几种可行的实现方式:
方法1:用FindFirstFileW遍历路径组件验证
FindFirstFileW会返回文件系统中实际存储的文件名(包含正确大小写),我们可以拆分路径的每个目录/文件组件,逐层查询真实名称:
#include <windows.h> #include <string> #include <vector> #include <algorithm> std::wstring GetRealCasePath(const std::wstring& inputPath) { std::wstring realPath; std::wstring currentDir = L".\\"; std::vector<std::wstring> components; // 拆分路径组件(处理绝对/相对路径) size_t pos = 0; std::wstring remaining = inputPath; if (!inputPath.empty() && inputPath[1] == L':') { realPath = inputPath.substr(0, 2); currentDir = realPath; remaining = inputPath.substr(2); } while ((pos = remaining.find(L'\\')) != std::wstring::npos) { components.push_back(remaining.substr(0, pos)); remaining = remaining.substr(pos + 1); } if (!remaining.empty()) { components.push_back(remaining); } // 逐层查询真实名称 for (const auto& comp : components) { WIN32_FIND_DATAW findData; HANDLE hFind = FindFirstFileW((currentDir + L"\\" + comp).c_str(), &findData); if (hFind == INVALID_HANDLE_VALUE) { return L""; // 路径不存在,返回空 } FindClose(hFind); realPath += L"\\" + std::wstring(findData.cFileName); currentDir = realPath; } return realPath; }
使用时,将用户输入的路径转换为宽字符串,调用此函数得到真实路径,再与原输入对比(区分大小写):
std::wstring input = L"Foo.txt"; std::wstring realPath = GetRealCasePath(input); if (realPath.empty() || input != realPath.substr(realPath.find_last_of(L'\\') + 1)) { // 文件名大小写不匹配,拒绝操作 // 比如返回Lua错误,或让文件打开失败 }
方法2:用GetFinalPathNameByHandleW获取完整真实路径
通过CreateFileW打开文件/目录获取句柄,再调用此函数获取文件系统存储的真实路径:
#include <windows.h> #include <string> std::wstring GetRealFullPath(const std::wstring& inputPath) { HANDLE hFile = CreateFileW(inputPath.c_str(), GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, nullptr); if (hFile == INVALID_HANDLE_VALUE) { return L""; } wchar_t buffer[MAX_PATH]; DWORD len = GetFinalPathNameByHandleW(hFile, buffer, MAX_PATH, VOLUME_NAME_DOS); std::wstring realPath; if (len > 0 && len <= MAX_PATH) { realPath = buffer; // 去掉可能的\\?\前缀 if (realPath.substr(0, 4) == L"\\\\?\\") { realPath = realPath.substr(4); } } CloseHandle(hFile); return realPath; }
同样,对比真实路径和用户输入的路径,若大小写不一致则触发错误。
为什么GetFullPathName不适用?
GetFullPathName仅负责将相对路径转换为绝对路径,不会查询文件系统的真实文件名存储形式,返回的路径大小写与用户输入完全一致,无法满足验证需求。
集成到Lua绑定的思路
在Lua绑定的文件操作接口(如打开文件、查询路径)中,先调用上述函数获取真实路径:
- 若路径不存在:直接返回错误
- 若路径存在但大小写与用户输入不匹配:同样返回错误,模拟Linux下的行为
这样就能确保mod在Windows开发时,一旦依赖大小写不敏感特性就会立即报错,避免到Linux环境崩溃。
内容的提问来源于stack exchange,提问作者MyNameIsTrez
相关产品推荐
相关产品推荐

