ifstream中文路径问题分析
2014-12-31 16:55
218 查看
最近维护一个项目,遇到了ifstream在中文路径下打开文件失败的bug,我搜索了一下,最后整理成下文以后日后查阅。
一、问题重现
vs2008下创建一个简单win32工程。 使用ANSI编码方式:项目属性页 ->配置属性 ->常规 ->项目默认值 ->字符集中选择"使用多字节字符集"。 简单出错代码:
运行输出结果:Open fail error code:3。
GetLastError()错误代码:3 系统找不到指定的路径; 而选择“使用 Unicode 字符集”时则无此问题出现;说明 是字符编码的问题,ifstream的open方法对传进入的中文窄字符处理可能存在问题。
二、原因分析
跟进ifstream的open方法可以发现,在其内部是用mbstowcs_s来实现窄字符转化成宽字符的。
msdn:mbstowcs_s uses the current locale for any locale-dependent behavior (mbstowcs_s的调用结果依赖于程序的本地化设置)。
本地化设置可以通过setlocale函数来设置,例如:setlocale(LC_ALL, "chinese")表示将程序本身的语言设置为中文,而程序启动时默认设置为LC_ALL="C"。
在使用mbstowcs_s进行字符串转换时,只有当LC_ALL="chinese"时,含中文的字符串才能正确的转换成其对应的宽字节字符,否则(在LC_ALL="C"时),汉字会被看成2个单字节的字符,然后再转换成宽字节的字符,这样转换的结果显然是错误的!
这就是ifstream打开含中文路径的文件失败的原因,因为"D:\\测试\\test.cpp"转换后得到错误的路径,所以找不到指定路径!
三、解决方法
最好的方法就是使用“使用 Unicode 字符集”,因为不但可以避免此类问题,而且也提升的程序执行效率(系统底层都是使用宽字节的 window 核心程序有说)
如果是历史项目不方便大改的话,可以有以下两种方法实现,展示代码如下:
一、问题重现
vs2008下创建一个简单win32工程。 使用ANSI编码方式:项目属性页 ->配置属性 ->常规 ->项目默认值 ->字符集中选择"使用多字节字符集"。 简单出错代码:
#include "stdafx.h" #include <Windows.h> #include <fstream> int _tmain(int argc, _TCHAR* argv[]) { std::ifstream infofile; infofile.open(_T("D:\\测试\\test.cpp")); if (infofile.is_open()) { printf("Open success!!!\r\n"); } else { printf("Open fail error code:%d\r\n", GetLastError()); } return 0; }
运行输出结果:Open fail error code:3。
GetLastError()错误代码:3 系统找不到指定的路径; 而选择“使用 Unicode 字符集”时则无此问题出现;说明 是字符编码的问题,ifstream的open方法对传进入的中文窄字符处理可能存在问题。
二、原因分析
跟进ifstream的open方法可以发现,在其内部是用mbstowcs_s来实现窄字符转化成宽字符的。
msdn:mbstowcs_s uses the current locale for any locale-dependent behavior (mbstowcs_s的调用结果依赖于程序的本地化设置)。
本地化设置可以通过setlocale函数来设置,例如:setlocale(LC_ALL, "chinese")表示将程序本身的语言设置为中文,而程序启动时默认设置为LC_ALL="C"。
在使用mbstowcs_s进行字符串转换时,只有当LC_ALL="chinese"时,含中文的字符串才能正确的转换成其对应的宽字节字符,否则(在LC_ALL="C"时),汉字会被看成2个单字节的字符,然后再转换成宽字节的字符,这样转换的结果显然是错误的!
这就是ifstream打开含中文路径的文件失败的原因,因为"D:\\测试\\test.cpp"转换后得到错误的路径,所以找不到指定路径!
三、解决方法
最好的方法就是使用“使用 Unicode 字符集”,因为不但可以避免此类问题,而且也提升的程序执行效率(系统底层都是使用宽字节的 window 核心程序有说)
如果是历史项目不方便大改的话,可以有以下两种方法实现,展示代码如下:
std::ifstream infofile; // 方法1,使用STL中的locale类的静态方法指定全局locale std::locale::global(std::locale("")); //将全局区域设为操作系统默认区域 infofile.open("D:\\测试\\test.cpp"); //可以顺利打开文件了 std::locale::global(std::locale("C")); //还原全局区域设定 // 方法2,使用C函数setlocale TCHAR* ptOldLocale = _tcsdup(_tsetlocale(LC_CTYPE, NULL)); //获取本地语言保存 _tsetlocale(LC_CTYPE, _T("")); //C语言的全局locale设置为本地语言,但这会导致cout和wcout不能输出中文 infofile.open("D:\\测试\\test.cpp"); //可以顺利打开文件了 _tsetlocale(LC_CTYPE, ptOldLocale); //将C语言的全局locale恢复
相关文章推荐
- ifstream打开含中文路径文件时失败的问题
- 关于std::fstream以及std::ifstream打开中文路径名失败的问题和解决方法
- ifstream VS2005 中文路径打开失败问题
- VC中ifstream中文路径读取失败的问题
- 关于std::fstream以及std::ifstream打开中文路径名失败的问题和解决方法
- ifstream打开中文路径的问题
- 剖析ifstream打开含中文路径名文件失败的原因
- ifstream & ofstream 打开中文路径失败的解决方案
- 剖析ifstream打开含中文路径名文件失败的原因
- 剖析ifstream打开含中文路径名文件失败的原因
- 转 ifstream 读取中文路径
- 关于GDAL180中文路径不能打开的问题分析与解决
- 解决std::ofstream操作中文路径下文件的问题
- ifstream ifile("中文路径")
- ofstream 解决中文路径问题
- 剖析ifstream打开含中文路径名文件失败的原因
- 解决std::ofstream操作中文路径下文件的问题
- 关于GDAL180中文路径不能打开的问题分析与解决
- 剖析ifstream打开含中文路径名文件失败的原因(转)
- 关于GDAL180中文路径不能打开的问题分析与解决