如何使用标准API打开和读取具有unicode路径或文件名的文件内容?

时间:2014-11-02 14:00:12

标签: c++ windows unicode filestream gcc4.7

如何打开文件路径或文件名包含unicode字符并在不使用任何特殊API的情况下读取或写入内容?如果可能或仅使用Windows API,如何仅使用std库?我确实尝试使用std :: wifstream打开一个文件,如下面的代码示例所示,但它没有编译。看起来它没有采取' const wchar_t *'参数但是' const char *'。我使用的是Dev-C ++ IDE附带的TDM-GCC 4.7.1编译器。

#ifndef UNICODE
#define UNICODE
#endif
...
#include <clocale>
#include <windows.h>
#include <fstream>
...
int main(int argc, char **argv)
{
    setlocale(LC_ALL, "Polish_Poland.852") ;
    ...
    fileCompare(first, second) ;
    ...
}
...
bool fileCompare(wstring first, wstring second)  // This function doesn't compile !
{
    using namespace std ;
    wifstream fin0(first.c_str(), ios::binary) ;
    wifstream fin1(second.c_str(), ios::binary) ;
    ...
}

一些完整的例子:

#ifndef UNICODE
#define UNICODE
#endif

#include <clocale>
#include <conio.h>
#include <windows.h>
#include <fstream>
#include <string>
#include <iostream>

using namespace std ;

bool fileCompare(wstring first, wstring second) ;

int main(int argc, char **argv)
{
    setlocale(LC_ALL, "Polish_Poland.852") ;

    wstring first, second ;
    first = L"C:\\A.dat" ;
    second = L"C:\\E.dat" ;

    fileCompare(first, second) ;

    getch() ;
    return 0 ;
}

bool fileCompare(wstring first, wstring second)  // This function doesn't compile !
{
    wifstream fin0(first.c_str(), ios::binary) ;
    wifstream fin1(second.c_str(), ios::binary) ;

}

当我更换L&#34; C:\ A.dat&#34;和L&#34; C:\ E.dat&#34;对于包含波兰语字符的字符串,它会输出有关非法字节序列的错误。

1 个答案:

答案 0 :(得分:0)

wifstream不处理文件名编码问题。据我所知,wifstream和ifstream的文件名都是基于char而不是基于wchar_t的。您必须以操作系统使用的字符编码提供文件名,例如latin1,utf8等..

然而,wifstream使您能够读取wchar_t流。您可以通过 imbuing 流来告诉流您期望的输入:

e.g。

 // We expect the file to be UTF8 encoded
 std::locale locale("en_US.utf8");
 fin0.imbue(locale);

编辑:如果您需要将文件名(或任何字符串)从wchar_t转换为适当的字符编码,您可以深入了解codecvt facets语言环境的主题。

// Method translates wchar_t => pl_PL.iso88592" encoding
std::string to_string(const std::wstring & wstr)  
{ 

    typedef std::codecvt< wchar_t, char, std::mbstate_t > ccvt_t;  

    std::locale loc("pl_PL.iso88592");    

    const ccvt_t & facet = std::use_facet<ccvt_t>( loc );  

    std::string s;  
    {  
        std::mbstate_t st=mbstate_t();  

        const wchar_t *wac = wstr.c_str();  
        const wchar_t *wou = wac + wstr.length();  
        const wchar_t *wnx = wac;   

        ccvt_t::result r = ccvt_t::ok;  

        while(wou!=wnx && (r==ccvt_t::ok || r==ccvt_t::partial))  
        {  
            static const int l = 100;  
            static char cou[l];  
            char *cnx=NULL;  
            r = facet.out(st,wac,wou,wnx,cou,cou+l,cnx);  
            s+=std::string(cou,cnx-cou);  
            wac=wnx;  
        }  
    }  

    return s;  
} 

支持哪种std :: locale以及如何指定它可能取决于操作系统。