ソフトウェア開発 Win32プログラミング

UTF-8をUnicodeに変換する

戻る


文字コードのUTF-8をUnicodeに変換する方法を以下に示す。

#include <windows.h>

INT cch;
WCHAR szWide[1024];
cch = MultiByteToWideChar(CP_UTF8, 0, szUTF8, -1, szWide, 1024);
szWide[cch] = 0;

しかし、この方法は、Windows 98/Me/NT 4.0 以降でなければ使えない。

Windows 95でも変換できるようにするには、次のようにするとよい。

#include <windows.h>
#include <cstdlib>
#include <cstdio>
#include <cstring>
using namespace std;

LPWSTR APIENTRY ConvertUTF8ToUnicode(LPCSTR pszUTF8, INT cch, BOOL *pfCESU8)
{
    LPWSTR pszWide, pch;
    UINT wch, x;
    BYTE b0, b1;
    CONST BYTE *pb = (CONST BYTE *)pszUTF8;

    *pfCESU8 = FALSE;
    pch = pszWide = new WCHAR[cch + 1];
    while(cch > 0)
    {
        if ((*pb & 0x80) == 0)
        {
            *pch++ = (WCHAR)*pb;
            pb++;
            cch--;
        }
        else if (cch >= 2 && 
                 (pb[0] & 0xE0) == 0xC0 && 
                 (pb[1] & 0xC0) == 0x80)
        {
            b0 = (BYTE)((pb[0] << 6) | (pb[1] & 0x3F));
            b1 = (BYTE)((pb[0] & 0x1C) >> 2);
            *pch++ = MAKEWORD(b0, b1);
            pb++;
            pb++;
            cch--;
            cch--;
        }
        else if (cch >= 3 && 
                 (pb[0] & 0xF0) == 0xE0 && 
                 (pb[1] & 0xC0) == 0x80 &&
                 (pb[2] & 0xC0) == 0x80)
        {
            b0 = (BYTE)((pb[2] & 0x3F) | ((INT)(pb[1] & 0x03) << 6));
            b1 = (BYTE)(((INT)(pb[0] & 0x0F) << 4) | ((pb[1] & 0x3C) >> 2));
            *pch = MAKEWORD(b0, b1);
            if (0xD800 <= *pch && *pch <= 0xDBFF)
                *pfCESU8 = TRUE;
            pch++;
            pb += 3;
            cch -= 3;
        }
        else if (cch >= 4 &&
                 (pb[0] & 0xF8) == 0xF0 && 
                 (pb[1] & 0xC0) == 0x80 &&
                 (pb[2] & 0xC0) == 0x80 &&
                 (pb[3] & 0xC0) == 0x80)
        {
            wch = ((UINT)(pb[0] & 0x03) << 18) |
                  ((UINT)(pb[1] & 0x3F) << 12) |
                  ((UINT)(pb[2] & 0x3F) << 6) |
                   (UINT)(pb[3] & 0x3F);
            x = wch - 0x10000;
            *pch++ = (WORD)(x / 0x400 + 0xD800);
            *pch++ = (WORD)(x % 0x400 + 0xDC00);
            pb += 4;
            cch -= 4;
        }
        else if (cch >= 5 &&
                 (pb[0] & 0xFC) == 0xF8 && 
                 (pb[1] & 0xC0) == 0x80 &&
                 (pb[2] & 0xC0) == 0x80 &&
                 (pb[3] & 0xC0) == 0x80 &&
                 (pb[4] & 0xC0) == 0x80)
        {
            *pch++ = '?';
            pb += 5;
            cch -= 5;
        }
        else if (cch >= 6 &&
                 (pb[0] & 0xFE) == 0xFC && 
                 (pb[1] & 0xC0) == 0x80 &&
                 (pb[2] & 0xC0) == 0x80 &&
                 (pb[3] & 0xC0) == 0x80 &&
                 (pb[4] & 0xC0) == 0x80 &&
                 (pb[5] & 0xC0) == 0x80)
        {
            *pch++ = '?';
            pb += 6;
            cch -= 6;
        }
        else
        {
            *pch++ = '?';
            pb++;
            cch--;
            while(cch > 0 && (*pb & 0xC0) == 0x80)
            {
                pb++;
                cch--;
            }
        }
    }
    *pch = 0;
    return pszWide;
}

int main(void)
{
    CHAR szUTF8[1024];
    LPWSTR pszWide;
    CHAR szANSI[1024];
    INT cch;
    FILE *fp;
    BOOL f;

    fp = fopen("utf8.txt", "r");
    fgets(szUTF8, 1024, fp);
    fclose(fp);

    if (strncmp(szUTF8, "\xEF\xBB\xBF", 3) == 0)
        MoveMemory(szUTF8, szUTF8 + 3, 1024 - 3);
    cch = strlen(szUTF8);
    pszWide = ConvertUTF8ToUnicode(szUTF8, cch, &f);
    cch = WideCharToMultiByte(CP_ACP, 0, pszWide, -1, szANSI, 1024,
                        NULL, NULL);
    szANSI[cch] = 0;
    delete[] pszWide;
    printf("%s\n", szANSI);
    return 0;
}

ソース: utf8wide.zip


戻る

©片山博文MZ
katayama.hirofumi.mz@gmail.com

inserted by FC2 system