大西彰のウェブログ

データベース系技術ネタ、国際化技術ネタなど、徒然なるままに

目次

Blog 利用状況

ニュース


こんにちは。大西 彰です。
私のブログでは、データベース技術、ソフトウェアの国際化などを取り扱っています。ニッチだけど重要なネタがつまっています。
ブログの内容は無保証です。
また、本ブログでの発言やコメントは、マイクロソフトの正式な見解またはコメントではありません。



マイクロソフトライセンスセンター
マイクロソフトライセンスセンター
マイクロソフトライセンスセンター
ウィルコムストア
ソースネクスト
デル株式会社
アフィリエイト リンクシェア ブログ 携帯対応 成果報酬 広告 テンプレート ブログパーツ

テクノラティプロフィール

記事のカテゴリ

過去の記事

カテゴリ

イメージギャラリ

My blog

Visual FoxPro

Visual Studio

Web Sites

Windows Vista

ブログ

免責事項

UTF-8文字列が入ったファイルをMBCSデータとして出力するプログラム: u2m.cpp

以下をテキストエディタにコピーし、u2m.cppとして保存してください。ポイントは、UTF-8からMBCSに直接変換することはできないということです。UTF-8文字列をいったんワイド文字列(UCS-2)に変換し、その後、ワイド文字列をMBCSに変換します。UTF-8からMBCSへの変換フィルターとしてご利用いただけます。

 

// u2m.cpp
// author: Akira Onishi / Copyright(c) 2004, Akira Onishi
// As of 2004.07.06
// Revised 2004.09.16 (コメントを英語から日本語にしただけ)
// このプログラムは、UTF-8文字列をMBCS文字列に変換する方法を示します。
// MultiByteToWideChar() と WideCharToMultiByte() APIを利用しています。
// あまり実用性があるかどうかわかりませんが、
// UTF-8で格納されたファイルを開きMBCS(日本語OSならシフトJIS)に変換して、
// 結果を標準出力に表示します。
// UTF-8のファイルにはBOMが付いていても付いていなくても構いません。
//
// コマンドプロンプトからは、次のようにするとコンパイルできます。
// cl u2m.cpp /link mfc71.lib (Visual C++.NET 2003)
// cl u2m.cpp /link mfc42.lib (Visual C++ 6.0)

#pragma once

#include <stdio.h>
#include <tchar.h>
#include <Afx.h>
#include <windows.h>
#include <winnls.h>

enum RESULT {
    OK,
    ARG_ERROR,
    FILE_ERROR,
    MEMORY_ERROR
};

void Usage(_TCHAR * exeName)
{
    fprintf(stderr, "usage: %s \n", exeName);
}

void FileError(_TCHAR * fileName)
{
    fprintf(stderr, "Cannot open file: [%s]\n", fileName);
}

void MemoryError(void)
{
    fprintf(stderr, "Not enough memory available in this system\n");
}

bool IsValidFilename(_TCHAR * fileName)
{
    FILE * fp;
    fp = fopen(fileName, "rb");
    if (fp == NULL) {
        return false;
    }
    fclose(fp);
    return true;
}

// UTF-8からMBCSへの変換: CStringクラス利用
int Utf8ToMbcsByCString(_TCHAR* fileName)
{
    FILE * fp;
    int nSize, nCode, nUCS2Length, nAcpLength;
    LPSTR pszUTF8 = NULL, pszAcp = NULL, pszUTF8noBOM = NULL;
    wchar_t * pszUCS2;

    fp = fopen(fileName, "rb");
    if (fp == NULL) {
        return FILE_ERROR;
    }
    nSize = 0;
    while ( !feof(fp) ) {
        nCode = fgetc(fp);
        nSize ++;
    }
    nSize ++;
    rewind(fp);
    pszUTF8 = (LPSTR)calloc( nSize, sizeof(char) );
    if ( pszUTF8 == NULL ) {
        MemoryError();
        return MEMORY_ERROR;
    }
    fread( pszUTF8, nSize, sizeof(char), fp);
    fclose(fp);
    // 読み込んだ文字列の先頭にBOMがあるかどうかを判定する
    if ( (unsigned char)pszUTF8[0] == 0xEF &&
         (unsigned char)pszUTF8[1] == 0xBB &&
         (unsigned char)pszUTF8[2] == 0xBF ) {
        pszUTF8noBOM = pszUTF8 + 3;
    }
    else {
        pszUTF8noBOM = pszUTF8;
    }
    // UTF-8文字列をBOM無しの状態でCStringに格納します
    CString utf8Buffer  = pszUTF8noBOM;
    // UTF-8からUCS-2(WindowsのUnicode)に変換した時の文字列の長さを
    // MultiByteToWideChar() APIで計算します
    nUCS2Length = MultiByteToWideChar(CP_UTF8, 0, utf8Buffer, -1,
                    NULL, 0 );
    if ( nUCS2Length > 0 ) {
        pszUCS2 = (wchar_t*)calloc( nUCS2Length, sizeof(wchar_t) );
        if ( pszUCS2 == NULL ) {
            MemoryError();
            free(pszUTF8);
            return MEMORY_ERROR;
        }
        // UTF-8文字列をUCS-2文字列に変換します
        MultiByteToWideChar(CP_UTF8, 0, utf8Buffer, -1,
            pszUCS2, nUCS2Length );
       
        // UCS-2文字列をMBCS文字列に変換したときの文字列の長さを
        // WideCharToMultiByte() APIで計算します。
        // 日本語WindowsにおいてGetACP()は、932を返します
        nAcpLength = WideCharToMultiByte(GetACP(), 0, pszUCS2, -1,
                        pszAcp, 0, NULL, NULL);
        if ( nAcpLength > 0 ) {
            pszAcp = (LPSTR)calloc( nAcpLength, sizeof(char) );
            if ( pszAcp == NULL ) {
                MemoryError();
                free(pszUTF8);
                free(pszUCS2);
                return MEMORY_ERROR;
            }
            // UCS-2文字列をMBCS文字列に変換します
            WideCharToMultiByte(GetACP(), 0, pszUCS2, -1, pszAcp,
                nAcpLength, NULL, NULL);
            // 結果を標準出力に送ります
            printf("%s", pszAcp );
            free(pszAcp);
        }
        free(pszUCS2);
    }
    free(pszUTF8);
    return OK;
}

// (参考):UTF-8からMBCSへの変換: 単なるunsigned char版
// ロジックはCStringの時とほぼ同じなのでコメントは省略
int Utf8ToMbcsByUchar(_TCHAR* fileName)
{
    FILE * fp;
    int nSize, nCode, nUCS2Length, nAcpLength;
    LPSTR pszUTF8 = NULL, pszAcp = NULL, pszUTF8noBOM = NULL;
    wchar_t * pszUCS2;
    fp = fopen(fileName, "rb");
    if (fp == NULL) {
        return FILE_ERROR;
    }
    nSize = 0;
    while ( !feof(fp) ) {
        nCode = fgetc(fp);
        nSize ++;
    }
    nSize ++;
    rewind(fp);
    pszUTF8 = (LPSTR)calloc( nSize, sizeof(char) );
    if ( pszUTF8 == NULL ) {
        MemoryError();
        return MEMORY_ERROR;
    }
    fread( pszUTF8, nSize, sizeof(char), fp);
    fclose(fp);
    if ( (unsigned char)pszUTF8[0] == 0xEF &&
         (unsigned char)pszUTF8[1] == 0xBB &&
         (unsigned char)pszUTF8[2] == 0xBF ) {
        pszUTF8noBOM = pszUTF8 + 3;
    }
    else {
        pszUTF8noBOM = pszUTF8;
    }
    LPSTR utf8Buffer  = pszUTF8noBOM;
    nUCS2Length = MultiByteToWideChar(CP_UTF8, 0, utf8Buffer,
                    -1, NULL, 0 );
    if ( nUCS2Length > 0 ) {
        pszUCS2 = (wchar_t*)calloc( nUCS2Length, sizeof(wchar_t) );
        if ( pszUCS2 == NULL ) {
            MemoryError();
            free(pszUTF8);
            return MEMORY_ERROR;
        }
        MultiByteToWideChar(CP_UTF8, 0, utf8Buffer, -1,
            pszUCS2, nUCS2Length );
        nAcpLength = WideCharToMultiByte(GetACP(), 0, pszUCS2,
            -1, pszAcp, 0, NULL, NULL);
        if ( nAcpLength > 0 ) {
            pszAcp = (LPSTR)calloc( nAcpLength, sizeof(char) );
            if ( pszAcp == NULL ) {
                MemoryError();
                free(pszUTF8);
                free(pszUCS2);
                return MEMORY_ERROR;
            }
            WideCharToMultiByte(GetACP(), 0, pszUCS2, -1, pszAcp,
                nAcpLength, NULL, NULL);
            printf("%s", pszAcp );
            free(pszAcp);
        }
        free(pszUCS2);
    }
    free(pszUTF8);
    return OK;
}

int _tmain(int argc, _TCHAR* argv[])
{
    if (argc!=2) {
        Usage(argv[0]);
        return ARG_ERROR;
    }
    if (IsValidFilename(argv[1]) == false) {
        FileError( argv[1] );
        return FILE_ERROR;
    }
    return Utf8ToMbcsByCString(argv[1]);    // MFC CStringを使った場合
    // return Utf8ToMbcsByUchar(argv[1]);    // unsigned charを使った場合
}

投稿日時 : 2004年9月16日 17:56

コメントを追加

# UTF-8からMBCSへの変換 2004/09/16 18:02 大西彰のウェブログ

UTF-8からMBCSへの変換

# re: UTF-8文字列が入ったファイルをMBCSデータとして出力するプログラム: u2m.cpp 2004/09/17 15:45 大西 彰

自己レス。
よく考えてみたら、このブログシステム、文字コードがUTF-8だから、Webブラウザからソースを保存して、このフィルターにかければ、SJISで読むことができますね。
自分のホームを修正するのに早速使ってみました(^^)

タイトル  
名前  
URL
コメント