MFC Unicode环境下如何将wstring文件路径转换为string类型供stbi_load使用
解决方案
方案1:Windows API转UTF-8编码string(兼容所有版本stb_image,最稳妥)
stbi_load原生支持UTF-8编码的路径,你只需要借助Windows系统API把wstring转成UTF-8编码的string即可,代码可直接复用:
#include <windows.h> #include <string> // wstring转UTF-8编码的string通用工具函数 std::string wstring_to_utf8(const std::wstring& wstr) { if (wstr.empty()) return {}; // 计算转换需要的缓冲区长度 int size_needed = WideCharToMultiByte(CP_UTF8, 0, wstr.c_str(), (int)wstr.size(), NULL, 0, NULL, NULL); std::string str(size_needed, 0); // 执行编码转换 WideCharToMultiByte(CP_UTF8, 0, wstr.c_str(), (int)wstr.size(), &str[0], size_needed, NULL, NULL); return str; }
调用方式如下:
std::wstring wstringPath = L"abc路徑"; std::string utf8Path = wstring_to_utf8(wstringPath); unsigned char *data = stbi_load(utf8Path.c_str(), &width, &height, &nrComponents, 0);
方案2:直接使用stb_image宽字符接口(最简便)
如果你用的是较新版本的stb_image,只需要在引入头文件前定义STBI_WIN32_USE_WCHAR宏,就可以直接传wchar_t类型的路径,完全不需要做编码转换:
// 注意宏定义要写在引入stb_image.h之前 #define STBI_WIN32_USE_WCHAR #define STB_IMAGE_IMPLEMENTATION #include "stb_image.h" // 调用处直接传入wstring的c_str即可 std::wstring wstringPath = L"abc路徑"; unsigned char *data = stbi_loadW(wstringPath.c_str(), &width, &height, &nrComponents, 0);
方案3:读取文件到内存再加载(完全规避路径编码问题)
如果有特殊场景不想处理编码,也可以先把整个纹理文件读进内存,再调用stbi的内存加载接口,不需要把路径传递给stbi:
#include <fstream> #include <vector> std::wstring wstringPath = L"abc路徑"; std::ifstream file(wstringPath, std::ios::binary | std::ios::ate); std::streamsize size = file.tellg(); file.seekg(0, std::ios::beg); std::vector<char> buffer(size); if (file.read(buffer.data(), size)) { // 直接从内存数据加载纹理 unsigned char *data = stbi_load_from_memory((const stbi_uc*)buffer.data(), (int)buffer.size(), &width, &height, &nrComponents, 0); }
你之前的写法失效主要有两个原因:
sizeof(newPath)拿到的是char*指针本身的大小(32位程序为4字节、64位为8字节),不是你申请的内存空间长度,导致wcstombs最多只能写入几个字节的内容,路径稍长就会截断。wcstombs依赖系统当前C locale设置,默认不是UTF-8编码,转出来的多字节字符串stbi_load无法识别,包含非ASCII字符的路径会直接加载失败。
内容的提问来源于stack exchange,提问作者jie chen
相关产品推荐
相关产品推荐

