ifstream打開含中文路徑名文件失敗的原因


(源自:http://blog.csdn.net/suhuaiqiang_janlay/article/details/5963867

首先,用一個簡單的例子來重現一下我所遇到的問題:

(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   /*方法1,
 2   使用STL中的locale類的靜態方法指定全局locale                   
 3   使用該方法以后,cout可能不能正常輸出中文,十分蹊蹺                    
 4   我發現了勉強解決的方法:不要在還原區域設定前用cout或wcout輸出中文,
 5   否則后果就是還原區域設定后無法使用cout wcout輸出中文           
 6   */
 7   locale::global(locale(""));//將全局區域設為操作系統默認區域
 8   file.open("d://測試//測試文本.txt");//可以順利打開文件了
 9   locale::global(locale("C"));//還原全局區域設定
10   cout<<file.rdbuf();
11   file.close();

 

 

1   /* 方法2,使用C函數setlocale,不能用cout輸出中文的問題解決方法同上 */
2   setlocale(LC_ALL,"Chinese-simplified");//設置中文環境
3   file.open("c://測試//測試文本3.txt");//可以順利打開文件了
4   setlocale(LC_ALL,"C");//還原
5   cout<<file.rdbuf();
6   file.close();

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM