UTF-8到宽字符转换

时间:2012-05-27 14:22:01

标签: c++ c windows unicode

#ifndef UNICODE
#define UNICODE
#endif

#include <Windows.h>
#include <cstdio>
#include <fstream>

using namespace std;

int main()
{
    FILE* resFile;
    char multiByteStr[256];
    ifstream oFile;
    FILE* exampleFile;
    TCHAR buffer[256];      
    system("chcp 65001");

    resFile = _wfopen(L"foo",L"w, ccs=UTF-8");             
    fwprintf(resFile,L"%s",L"C:\\exsistingFolder\\zażółć gęśłą jaźń ☺☻♥♦• ć.txt");    
    fclose(resFile);   

    oFile.open(L"foo");    
    oFile.getline(multiByteStr,256,'\n');       
    oFile.close();    

    MultiByteToWideChar(CP_UTF8,0,multiByteStr,256,buffer,256);    
    wprintf(L"%s",buffer);

    exampleFile = _wfopen(buffer,L"w, ccs=UTF-16LE");       
    fwprintf(exampleFile,L"%s",buffer);     
    fclose(exampleFile);

    system("pause");
    return 0;
}

如您所见,程序应创建文件“foo”resFile,其中包含要创建的文件的完整路径,此新文件exampleFile应包含自身的路径。虽然在Visual Studio 2010中调试期间,autos会生成缓冲区具有正确的字符串,但不会创建exampleFile。为什么呢?
另一件事:为什么wprintf不输出扩展字符,虽然我已经将控制台的字体切换到Lucida控制台 - 那个可以处理解码字符的字体。

聚苯乙烯。 exampleFile指向NULL,即使在_wfopen之后,缓冲区的最后一个字符为'/0'

3 个答案:

答案 0 :(得分:2)

您没有进行任何错误处理。最重要的是,在调用MultiByteToWideChar()时,您告诉它转换整个multiByteStr缓冲区,但大多数缓冲区都包含垃圾,因为您事先没有将其归零。您必须使用缓冲区中的实际字符数,而不是缓冲区的最大大小。 MultiByteToWideChar()可能会返回您忽略的错误。代码中还有其他几个故障点。您需要始终检查错误,尤其是在与操作系统交互时。

试试这个:

#define UNICODE

#include <Windows.h>
#include <cstdio>
#include <fstream>

using namespace std;

void pause()
{
    wcin.ignore();
    wcin.get();
}

int main()
{
    FILE* resFile;
    char multiByteStr[256] = {0};
    ifstream oFile;
    FILE* exampleFile;
    WCHAR buffer[256] = {0};

    SetConsoleOutputCP(CP_UTF8);

    resFile = _wfopen(L"foo",L"w, ccs=UTF-8");
    if (!resFile) {
        wprintf(L"Unable to create foo");
        goto done;
    }

    fwprintf(resFile,L"%s",L"C:\\exsistingFolder\\zażółć gęśłą jaźń ☺☻♥♦• ć.txt");
    fclose(resFile);

    if (!oFile.open(L"foo")) {
        wprintf(L"Unable to open foo");
        goto done;
    }

    oFile.getline(multiByteStr,255,'\n');
    oFile.close();

    if (MultiByteToWideChar(CP_UTF8,0,multiByteStr,-1,buffer,256) == 0) {
        wprintf(L"Unable to convert UTF-8 to UTF-16. Error: %u", GetLastError());
        goto done;
    }

    exampleFile = _wfopen(buffer,L"w, ccs=UTF-16LE"); 
    if (!exampleFile) {
        wprintf(L"Unable to create file: %s", buffer);
        goto done;
    }

    fwprintf(exampleFile,L"%s",buffer); 
    fclose(exampleFile);

    wprintf(L"created file: %s", buffer);

done:
    pause();
    return 0;
}

答案 1 :(得分:1)

为什么混合和匹配您的I / O库?这是一个纯(Windows)C解决方案,减去错误检查:

#include <stdio.h>
#include <stdlib.h>

int main()
{
    FILE* pFile;
    wchar_t buffer[256];

    _wfopen_s(&pFile,L"foo",L"w, ccs=UTF-8");
    fputws(L"C:/existingFolder/zażółć gęśłą jaźń ☺☻♥♦• ć.txt",pFile);
    fclose(pFile);

    _wfopen_s(&pFile,L"foo",L"r, ccs=UTF-8");
    fgetws(buffer,_countof(buffer),pFile);
    fclose(pFile);

    _wfopen_s(&pFile,buffer,L"w, ccs=UTF-16LE");
    fputws(buffer,pFile);
    fclose(pFile);

    return 0;
}

答案 2 :(得分:1)

解决方案非常简单 - _wfopen使用BOM 创建以UTF-8 编码的文件,而MultiByteToWideChar函数不会删除BOM,因此我们需要手动删除它。