ifstream中文路径问题分析
最近维护一个项目,遇到了ifstream在中文路径下打开文件失败的bug,我搜索了一下,最后整理成下文以后日后查阅。
一、问题重现
- 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中文路径问题分析的更多相关文章
- 浅析GDAL库C#版本支持中文路径问题
GDAL库对于C#的支持问题还是蛮多的,对于中文路径的支持就是其中之一(另一个就是通过OGR库获取图形的坐标信息). 关于C#支持中文路径,看过我之前博客的应该都不陌生,如果使用的是我修改过的GDAL ...
- GDAL打开HDF格式时遇到的中文路径问题(未解决)
众所周知,中文环境下(VS2010 C++工程编码为多字节编码),在使用1.8.0版本以后的GDAL打开中文路径下的影像文件(如GeoTiff文件)时, 需对中文文件路径做特殊处理,有2种方法:(我使 ...
- QGis、Gdal本地中文路径问题
编译qgis完整项目后,由于Gdal库的原因,中文路径下通过添加矢量数据中数据库中是没有OGR的Oracle数据库功能的: 最开始打算通过重新编译gadl库从内部支持中文的(有成功的麻烦也请告诉我), ...
- CentOS个人目录下中文路径转英文路径
CentOS个人目录下中文路径转英文路径 如果安装了中文版到CentOS之后,root目录及home目录下会出现中文到路径名,如"桌面"."文档"," ...
- Atitit.url 汉字中文路径 404 resin4 resin 解决 v2 q329
Atitit.url 汉字中文路径 404 resin4 resin 解决 v2 q329 1. Pluginx机制1 2. Code1 3. 参考4 1. 原理 过滤器 ,,拦截jpg w ...
- 解决ckeditor中文路径无法下载,无法显示图片问题
使用ckfinder上传的文件如果是中文路径,下载的时候会找不到 假如使用tomcat服务器,找到tomcat目录>conf文件夹的server.xml>用查找找到Connector这个 ...
- 解决 git 中文路径显示 unicode 代码的问题
解决 git 中文路径显示 unicode 代码的问题 当被修改的文件中带有中文字符时,中文字符会被转换为 unicode 代码,看不出原来的文件名. 这时,只要配置 :: git config -- ...
- 关于 MAXScript 中文路径返回上级目录(精简版)
之前写过一个 关于 MAXScript 中文路径返回上级目录 的博文 今天无意中发现了一个更简单的方法 代码如下: fn newfile filepath = ( nf = getfilenamepa ...
- struts2中form提交到action中的中文参数乱码问题解决办法(包括取中文路径)
我的前台页是这样的: <body> <form action="test.action" method="post"> ...
随机推荐
- mysql索引之唯一索引
mysql 的唯一索引一般用于不重复的字段,一般会把表中的id设为唯一索引,创建唯一索引的目的不是为了提高查询速度,而是为了避免数据重复,注意:唯一索引可以有多个,但是列值必须唯一,创建唯一索引使用关 ...
- php 之 房屋租赁练习(0509)
做出以下页面并实现其对应的功能: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "h ...
- js获取下拉列表(select)选中项的值和文本
获取下拉列表选中项的值和文本(select) <html> <head> <meta charset="utf-8"/> <title&g ...
- C程序设计语言练习题1-8
练习1-8 编写一个统计空格.制表符与换行符个数的程序. 代码如下: #include <stdio.h> // 包含标准库的信息. int main() // 定义名为main的函数,它 ...
- Selenium2Library关键字
对Selenium2Library关键字的整理和翻译.英文不好,仅供参考. 1.Add Cookie [ name | value | path=None | domain=None | secure ...
- bzoj 2075: [POI2004]KAG
整天鬼畜题搞搞,感觉药丸…… 这种题出到xjoi模拟题里,太神了…… 这题的核心在于分割Cograph,尝试把Cograph的合成过程给求出来. 我们将这张图中的边为黑边,在这张图的补图中出现的边为白 ...
- [转]RegOpenKeyEx函数失败的问题
在使用这个函数RegOpenKeyEx的时候,老是执行不成功,函数本身返回2,GetLastError返回0.在CSDN上查阅资料说是返回2的原因是注册表中对应路径不存在,可是我电脑中注册表那个键值明 ...
- 初识Mybatis框架,实现增删改查等操作
此第一次接触Mybatis框架确实是有点不适应,特别是刚从Hibernate框架转转型过来,那么为什么要使用Mybatis框架,Mybatis框架和Hibernate框架又有什么异同呢? 这个问题在我 ...
- 奇葩的SQL*Net more data from client等待,导致批处理巨慢
<pre name="code" class="sql"><pre name="code" class="sql ...
- linux/unix 段错误捕获【续】
本文为“在C/C++中捕获段错误,打印出错的具体位置”的续篇,进一步解决涉及动态链接库的情况. 背景知识: ·linux/unix下动态链接库的基本原理 ·/proc/pid/maps文件的基本格 ...