// 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を使った場合
}