fstream::open不能打开带中⽂的⽂件路径(转)
原⽂地址:
⾸先,⽤⼀个简单的例⼦来重现⼀下我所遇到的问题:
(1)在VS2008的“Property  Pages”属性页中,选择“Configuration Properties”-->“General”,可以看到当前使⽤的字符集是“Multi-Byte Character Set”,也就是说程序中使⽤的是多字节字符集。
(2)接下来看看ifstream打开txt⽂件的简单代码:
1. #include "stdafx.h"
2. #include <fstream>
3. #include <iostream>
4. using namespace std;
5. int _tmain(int argc, _TCHAR* argv[])
6. {
7.    ifstream infile("d://测试.txt");
8.    if(infile.is_open())
9.    {
10.        cout<<"Open Success!";
11.    }
12.    else
13.    {
14.        cout<<"Open Fail!";
15.    }
16.    return 0;
17. }
(3)运⾏结果:输出“Open Fail”  (打开⽂件失败!)
从设置选项中可以看到,⼯程中使⽤的字符集可设置为“Multi-Byte Character Set”或“Unicode Character Set”,其中“Multi-Byte Character Set”表⽰使⽤ANSI编码⽅式,“Unicode Character Set”表⽰使⽤UNICODE编码⽅式。
那么这两种编码⽅式有什么样的区别呢?
(1)传统的计算机使⽤ANSI编码,在ANSI编码模式下,英⽂字符都⽤1个字节表⽰,⽽某些其它国家的⽂字(如汉字、⽇⽂),⽆法⽤单个字节来表⽰,ANSI便采⽤多个字节来表⽰这些字符(汉字是2个字节)。
(2)UNICODE包含UTF-8、UTF-16、UTF-32等多种编码⽅案(⽬前windows⼀般使⽤UTF-16)。拿UTF-16来说,规定所有字符都使⽤2个字节表⽰(不论英⽂字母还是汉字),对于超出2个字节范围的字符采⽤代理(采⽤4个字节表⽰)。
UNICODE相⽐ANSI有很多⽅⾯的优势(优势体现在哪?),微软⾮常提倡使⽤UNICODE编码⽅式,在MS较新版本的系统中都是采⽤UNICODE编码的。因此,即便我们在⾃⼰写的程序中使⽤了ANSI编码,系统会将其转换为UNICODE再对其进⾏处理。
接下来我们说⼀下ifstream。在调⽤ifstream的open⽅法时,系统内部调⽤mbstowcs_s进⾏⽂件名转换(mbstowcs_s函数的作⽤是把多字节字符转化为宽字符),需要注意的是,该函数的调⽤结果依赖于程序的本地化设置(什么是本地化设置?)。⽽本地化设置可以通过setlocale函数来设置,譬如:setlocale(LC_ALL, "chinese")表⽰将程序本⾝的语⾔设置为中⽂,⽽程序启动时默认设置为LC_ALL="C"。在使⽤mbstowcs_s进⾏字符串转换时,只有当LC_ALL="chinese"时,含中⽂的字符串才能正确的转换成其对应的宽字节字符,否则(在
LC_ALL="C"时),汉字会被看成2个单字节的字符,然后再转换成宽字节的字符,这样转换的结果显然是错误的!这就是ifstream打开含中⽂路径的⽂件失败的原因,因为"d://测试.txt"转换后得到错误的路径,因此⽂件打不开!
解决⽅法如下:
1: /********************************************************************
2: created: 2008/05/10
3: created: 10:5:2008 23:56
4: filename: k:/sj/fstreamTest/fstreamTest/main.cpp
5: file path: k:/sj/fstreamTest/fstreamTest
6: file base: main
7: file ext: cpp
8: author: Gohan
9: *********************************************************************/
10: #include <tchar.h>
11: #include <fstream>
12: #include <iostream>
13: using namespace std;
14: int main()
15: {
16: /************************************************************************/
17: /* ⽅法1,使⽤_TEXT()宏定义将字符串常量指定为TCHAR*类型 */
18: /* 如果是我,⾸选此类型 */
19: /************************************************************************/
20: fstream file;
21: file.open(_TEXT("c://测试//测试⽂本.txt"));
22: cout<<file.rdbuf();
23: file.close();
24:
properties在哪打开
25: /************************************************************************/
26: /* ⽅法2,使⽤STL中的locale类的静态⽅法指定全局locale */
27: /* 使⽤该⽅法以后,cout可能不能正常输出中⽂,⼗分蹊跷 */
28: /* 我发现了勉强解决的⽅法:不要在还原区域设定前⽤cout或wcout 输出中⽂ */
29: /* 否则后果就是还原区域设定后⽆法使⽤cout wcout输出中⽂ */
30: /************************************************************************/
31: locale::global(locale(""));//将全局区域设为操作系统默认区域
32: file.open("c://测试//测试⽂本2.txt");//可以顺利打开⽂件了
33: locale::global(locale("C"));//还原全局区域设定
34: cout<<file.rdbuf();
35: file.close();
36:
37: /************************************************************************/
38: /* ⽅法3,使⽤C函数setlocale,不能⽤cout输出中⽂的问题解决⽅法同上 */
39: /************************************************************************/
40: setlocale(LC_ALL,"Chinese-simplified");//设置中⽂环境
41: file.open("c://测试//测试⽂本3.txt");//可以顺利打开⽂件了
42: setlocale(LC_ALL,"C");//还原
43: cout<<file.rdbuf();
44: file.close();
45: }
参见博客:
由于windows提倡使⽤UNICODE编码,因此,我们在使⽤VS编写程序的时候,最好也都使⽤UNICODE字符集。这样有利于避免字符集转换带来的问题,同时,也有利于提⾼效率(前⾯提到,windows内部会把ANSI编码转换为UNICODE再处理,这些转换当然也带来了额外的时间消耗)。
在⽰例的程序中,可以将⼯程字符集设置为UNICODE,然后将字符串前⾯加上_T(这样,在字符集已经设置为UNICODE的情况下,该字符串会⾃动采⽤宽字符表⽰),例如:ifstream infile(_T("d://测试.txt")),便不会有打开⽂件不成功的问题了。

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。