×

[PR]この広告は3ヶ月以上更新がないため表示されています。
ホームページを更新後24時間以内に表示されなくなります。


UTF-16 to EUC-JP への文字コード変換のサンプル実装。
MinGW + gcc 3.4.2 環境において動作確認してあります。

以下の例は、Utf16ToEucJp()の実装の例です。 [utf16_to_euc_jp_c.zip]

Example Code
/*
 * file:utf16_to_euc_jp.c
 */
/** @file
 * @brief UTF-16 → EUC-JP への変換実装サンプルプログラム。
 * 
 * UTF-16 → EUC-JP への変換実装サンプルプログラム。
 * UTF-16 にて用意された"data.txt"ファイルを読み込み、
 * EUC-JP へと変換、
 * "out.txt"ファイルへと出力します。
 * 変換前の文字列にBOMが見つかれば、除去します。
 */
#define STRICT

#include <locale.h>
#include <stdio.h>
#include <string.h>
#include <wchar.h>

#include "utf16_to_euc_jp_table.h"

#define DEFAULT_BUFF_LEN    4096

int printUsage();
int Utf16ToEucJp(char *dest, size_t dest_size, wchar_t *src
        , size_t src_size);

struct _OPTIONS
{
    char    i[DEFAULT_BUFF_LEN];
    char    o[DEFAULT_BUFF_LEN];
};

typedef struct _OPTIONS T_OPTIONS;

int main(int argc, char *argv[])
{
    wchar_t     buffer[DEFAULT_BUFF_LEN];
    int         convertCharCount    = 0;
    char        dest[DEFAULT_BUFF_LEN];
    size_t      dest_size           = 0;
    int         i                   = 0;
    int         iResult             = 0;
    int         n                   = 0;
    FILE        *pInputFile         = NULL;
    FILE        *pOutputFile        = NULL;
    wchar_t     *src                = NULL;
    size_t      src_size            = 0;
    T_OPTIONS   options;
    char        key[DEFAULT_BUFF_LEN];
    
    _wsetlocale(LC_ALL, L"japanese");
    
    /*
     * ●入力パラメタチェック
     */
    if (argc < 5)
    {
        printUsage();
        return 0;
    }
    else
    {
        memset(&options, 0, sizeof(options));
        memset(key, 0, DEFAULT_BUFF_LEN);
        for (i = 1; i < argc; i++)
        {
            if (*argv[i] == '-')
            {
                strcpy(key, argv[i]);
            }
            else
            {
                if (strcmp(key, "-i") == 0)
                {
                    strcpy(options.i, argv[i]);
                }
                else if (strcmp(key, "-o") == 0)
                {
                    strcpy(options.o, argv[i]);
                }
                strcpy(key, "");
            }
        }
    }
    if (*(options.i) == '\0' || *(options.o) == '\0')
    {
        printUsage();
        return 0;
    }
    
    /* 
     * ●ファイルを開く
     */
    pInputFile = fopen(options.i, "rb");
    if (pInputFile == NULL)
    {
        fwprintf(stderr, L"ファイルがひらけません: %s\n", options.i);
    }
    pOutputFile = fopen(options.o, "wb");
    if (pOutputFile == NULL)
    {
        fwprintf(stderr, L"ファイルがひらけません: %s\n", options.o);
    }
    
    if ((pInputFile != NULL) && (pOutputFile != NULL))
    {
        while (feof(pInputFile) == 0)
        {
            /* 
             * ●ファイル読込
             */
            memset(buffer, 0, sizeof(wchar_t) * DEFAULT_BUFF_LEN);
            n = DEFAULT_BUFF_LEN - 1;
            if (NULL == fgetws(buffer, n, pInputFile))
            {
                buffer[0] = L'\0';
            }
            
            src = buffer;
            
            /*
             * ●BOMの除去
             */
            if (*src == 0xfeff)
            {
                src++;
            }
            
            /* 
             * ●文字コード変換
             * UTF-16:src -> EUC-JP:dest 変換
             */
            memset(dest, 0, sizeof(char) * DEFAULT_BUFF_LEN);
            dest_size = DEFAULT_BUFF_LEN - 1;
            src_size = wcslen(src);
            iResult = Utf16ToEucJp(dest, dest_size, src, src_size);
            if (iResult == (-1))
            {
                fwprintf(stderr, L"Utf16ToEucJp() Failed.\n");
                if (pInputFile != NULL)
                {
                    fclose(pInputFile);
                    pInputFile = NULL;
                }
                if (pOutputFile != NULL)
                {
                    fclose(pOutputFile);
                    pOutputFile = NULL;
                }
                return 1;
            }
            convertCharCount += iResult;
            
            /* 
             * ●ファイル書込
             */
            fputs(dest, pOutputFile);
        }
    }
    
    /* 
     * ●ファイルを閉じる
     */
    if (pInputFile != NULL)
    {
        fclose(pInputFile);
        pInputFile = NULL;
    }
    if (pOutputFile != NULL)
    {
        fclose(pOutputFile);
        pOutputFile = NULL;
    }
    
    wprintf(L"%d バイト変換しました。\n", convertCharCount);
    
    return 0;
}

/**
 * printUsage() 関数。
 * 使用方法をコンソールに出力します。
 */
int printUsage()
{
    wprintf(L"utf16_to_euc_jp.exe\n");
    wprintf(L"UTF-16 から EUC-JP へ文字コードを変換します。\n");
    wprintf(L"使用法\n");
    wprintf(L"> utf16_to_euc_jp -i 入力ファイル -o 出力ファイル[Enter]\n");
    
    return 0;
}

/**
 * 文字コードを UTF-16 より EUC-JP へと変換。
 * 
 * @param[out] dest 出力文字列 EUC-JP
 * @param[in]  dest_size destのバイト数
 * @param[in]  src 入力文字列 UTF-16
 * @param[in]  src_size 入力文字列の文字数
 * 
 * @return 成功時には出力文字列のバイト数を戻します。
 *         dest_size に0を指定し、こちらの関数を呼び出すと、変換された
 *         文字列を格納するのに必要なdestのバイト数を戻します。
 *         関数が失敗した場合には、(-1)を戻します。
 */
int Utf16ToEucJp(char *dest, size_t dest_size, wchar_t *src
        , size_t src_size)
{
    long                countNeedsBytes     = 0;
    long                cursor              = 0;
    const char          dummy_code          = 0x3f;
    unsigned long       eucJpCode           = 0x000000;
    unsigned long       firstChar           = 0;
    unsigned long       firstIndex          = 0;
    unsigned long       secondChar          = 0;
    unsigned long       secondIndex         = 0;
    long                sizeBytes           = 0;
    wchar_t             unicode             = 0x0000;
    
    /*
     * 入力パラメータをチェック
     */
    if (dest_size == 0)
    {
        /*
         * dest_size == 0
         */
    }
    else
    {
        /*
         * dest_size != 0
         */
        if (dest == NULL)
        {
            /* Error : dest is NULL. */
            return (-1);
        }
        if (dest_size < 0)
        {
            /* Error : dest_size < 0. */
            return (-1);
        }
    }
    if (src == NULL)
    {
        /* Error : src is NULL. */
        return (-1);
    }
    if (src_size < 0)
    {
        /* Error : src_size < 0. */
        return (-1);
    }
    
    countNeedsBytes = 0;
    for (cursor = 0; cursor < src_size; cursor++)
    {
        /* srcより1ワードのデータを読み出し */
        unicode = *(src + cursor);
        eucJpCode = dummy_code;
        firstChar = (unicode >> 8) & 0x00ff;
        secondChar = (unicode) & 0x00ff;
        firstIndex = firstChar & 0x00ff;
        /* byType(1:isEmpty 2:BitmapIndex 3:Data) */
        if (utf16_to_euc_jp_table[firstIndex].byType == 2)
        {
            secondIndex = utf16_to_euc_jp_table[firstIndex].dwBitmapIndex
                    + secondChar;
            if (utf16_to_euc_jp_table[secondIndex].byType == 3)
            {
                eucJpCode = utf16_to_euc_jp_table[secondIndex].dwEucJpCode;
            }
        }
        if (eucJpCode <= 0x0000ff)
        {
            sizeBytes = 1;
        }
        else if (eucJpCode <= 0x00ffff)
        {
            sizeBytes = 2;
        }
        else
        {
            sizeBytes = 3;
        }
        
        /*
         * dest_size をチェック
         */
        if (dest_size && (dest_size < (countNeedsBytes + sizeBytes)))
        {
            /* Error : memory is not enough for dest */
            return countNeedsBytes;
        }
        
        if (dest_size)
        {
            if (eucJpCode == 0x0000)
            {
                /* 0x0000 */
                if (unicode == 0x0000)
                {
                    *(dest) = (char)0x00;
                    dest++;
                }
                else
                {
                    *(dest) = (char)dummy_code;
                    dest++;
                }
            }
            else if (sizeBytes == 1)
            {
                /* sizeBytes == 1 */
                *(dest) = (char)((eucJpCode) & 0x00ff);
                dest++;
            }
            else if (sizeBytes == 2)
            {
                /* sizeBytes == 2 */
                *(dest) = (char)((eucJpCode >> 8) & 0x00ff);
                dest++;
                *(dest) = (char)((eucJpCode) & 0x00ff);
                dest++;
            }
            else
            {
                /* sizeBytes == 3 */
                *(dest) = (char)((eucJpCode >> 16) & 0x00ff);
                dest++;
                *(dest) = (char)((eucJpCode >> 8) & 0x00ff);
                dest++;
                *(dest) = (char)((eucJpCode) & 0x00ff);
                dest++;
            }
        }
        countNeedsBytes += sizeBytes;
    }
    
    return countNeedsBytes;
}

・2008-10-03