在windows下,用纯c语言转换编码格式。
主要用到两个windows api 函数MultiByteToWideChar和WideCharToMultiByte。简单介绍这两个函数:
(1)MultiByteToWideChar:
MultiByteToWideChar(
_In_ UINT CodePage,
_In_ DWORD dwFlags,
_In_NLS_string_(cbMultiByte) LPCCH lpMultiByteStr,
_In_ int cbMultiByte,
_Out_writes_to_opt_(cchWideChar, return) LPWSTR lpWideCharStr,
_In_ int cchWideChar
);
参数说明:
CodePage:
指定要转换成的字符集代码页,它可以是任何已经安装的或系统自带的字符集,你也可以使用如下所示代码页之一。
CP_ACP 当前系统ANSI代码页
CP_MACCP 当前系统Macintosh代码页
CP_OEMCP 当前系统OEM代码页,一种原始设备制造商硬件扫描码
CP_SYMBOL Symbol代码页,用于Windows 2000及以后版本
CP_THREAD_ACP 当前线程ANSI代码页,用于Windows 2000及以后版本
CP_UTF7 UTF-7,设置此值时lpDefaultChar和lpUsedDefaultChar都必须为NULL
CP_UTF8 UTF-8,设置此值时lpDefaultChar和lpUsedDefaultChar都必须为NULL
dwFlags:
指定是否转换成预制字符或合成的宽字符,对控制字符是否使用像形文字,以及怎样处理无效字符。 MB_PRECOMPOSED 总是使用预制字符,即有单个预制字符时,就不会使用分解的基字符和不占空间字符。此为函数的默认选项,不能和MB_COMPOSITE合用
MB_COMPOSITE 总是使用分解字符,即总是使用基字符+不占空间字符的方式
MB_ERR_INVALID_CHARS 设置此选项,函数遇到非法字符就失败并返回错误码ERROR_NO_UNICODE_TRANSLATION,否则丢弃非法字符
MB_USEGLYPHCHARS 使用像形字符代替控制字符
/*对于下列代码页,dwFlags必须为0,否则函数返回错误码ERROR_INVALID_FLAGS。50220 50221 50222 50225 50227 50229 52936 54936 57002到57011 65000(UTF7) 42(Symbol)。对于UTF8,dwFlags必须为0或MB_ERR_INVALID_CHARS,否则函数都将失败并返回错误码ERROR_INVALID_FLAGS */
lpMultiByteStr:
指向将被转换字符串的字符
cbMultiByte:
指定由参数lpMultiByteStr指向的字符串中字节的个数。如果lpMultiByteStr指定的字符串以空字符终止,可以设置为-1(如果字符串不是以空字符中止,设置为-1可能失败,可能成功),此参数设置为0函数将失败。
lpWideCharStr:
指向接收被转换字符串的缓冲区。
cchWideChar:
指定由参数lpWideCharStr指向的缓冲区的宽字符个数。若此值为零,函数返回缓冲区所必需的宽字符数,在这种情况下,lpWideCharStr中的缓冲区不被使用。
返回值:
ERROR_INSUFFICIENT_BUFFER;
ERROR_INVALID_FLAGS;
ERROR_INVALID_PARAMETER;
ERROR_NO_UNICODE_TRANSLATION。
(2)WideCharToMultiByte:
WideCharToMultiByte(
_In_ UINT CodePage,
_In_ DWORD dwFlags,
_In_NLS_string_(cchWideChar) LPCWCH lpWideCharStr,
_In_ int cchWideChar,
_Out_writes_bytes_to_opt_(cbMultiByte, return) LPSTR lpMultiByteStr,
_In_ int cbMultiByte,
_In_opt_ LPCCH lpDefaultChar,
_Out_opt_ LPBOOL lpUsedDefaultChar
)
CodePage:
如上:
dwFlags:
指定如何处理没有转换的字符, 但不设此参数函数会运行的更快一些,一般都是把它设为0。 可设的值如下表所示:
WC_NO_BEST_FIT_CHARS 把不能直接转换成相应多字节字符的Unicode字符转换成lpDefaultChar指定的默认字符。也就是说,如果把Unicode转换成多字节字符,然后再转换回来,你并不一定得到相同的Unicode字符,因为这期间可能使用了默认字符。此选项可以单独使用,也可以和其他选项一起使用。
WC_COMPOSITECHECK 把合成字符转换成预制的字符。它可以与后三个选项中的任何一个组合使用,如果没有与他们中的任何一个组合,则与选项WC_SEPCHARS相同。
WC_ERR_INVALID_CHARS 此选项会致使函数遇到无效字符时失败返回,并且GetLastError会返回错误码ERROR_NO_UNICODE_TRANSLATION。否则函数会自动丢弃非法字符。此选项只能用于UTF8。
WC_DISCARDNS 转换时丢弃不占空间的字符,与WC_COMPOSITECHECK一起使用
WC_SEPCHARS 转换时产生单独的字符,此是默认转换选项,与WC_COMPOSITECHECK一起使用
WC_DEFAULTCHAR 转换时使用默认字符代替例外的字符,(最常见的如’?’),与WC_COMPOSITECHECK一起使用。
对于UTF8,dwFlags必须为0或WC_ERR_INVALID_CHARS,否则函数都将失败返回并设置错误码ERROR_INVALID_FLAGS,你可以调用GetLastError获得。
lpWideCharStr:
指向将被转换的unicode字符串。
cchWideChar:
指定由参数lpWideCharStr指向的缓冲区的字符个数。如果这个值为-1,字符串将被设定为以NULL为结束符的字符串,并且自动计算长度。
lpMultiByteStr:
指向接收被转换字符串的缓冲区。
cbMultiByte:
指定由参数lpMultiByteStr指向的缓冲区最大值(用字节来计量)。若此值为零,函数返回lpMultiByteStr指向的目标缓冲区所必需的字节数,在这种情况下,lpMultiByteStr参数通常为NULL。
lpDefaultChar:
lpUsedDefaultChar:
只有当WideCharToMultiByte函数遇到一个宽字节字符,而该字符在uCodePage参数标识的代码页中并没有它的表示法时,WideCharToMultiByte函数才使用这两个参数。如果宽字节字符不能被转换,该函数便使用lpDefaultChar参数指向的字符。如果该参数是NULL(这是大多数情况下的参数值),那么该函数使用系统的默认字符。该默认字符通常是个问号。这对于文件名来说是危险的,因为问号是个通配符。pfUsedDefaultChar参数指向一个布尔变量,如果Unicode字符串中至少有一个字符不能转换成等价多字节字符,那么函数就将该变量置为TRUE。如果所有字符均被成功地转换,那么该函数就将该变量置为FALSE。当函数返回以便检查宽字节字符串是否被成功地转换后,可以测试该变量。
返回值:
ERROR_INSUFFICIENT_BJFFER;
ERROR_INVALID_FLAGS;
ERROR_INVALID_PARAMETER;
ERROR_NO_UNICODE_TRANSLATION。
#include
#include
#include
#include
#define DEBUG 1
DWORD UTF8toSjis(char *dstSjis, char *srcUTF8)
{
int nRet = 0;
DWORD dwErr = 0;
int lengthUnicode = 0;
wchar_t* bufUnicode = NULL;
int lengthSJis = 0;
char* bufShiftJis = NULL;
int nSrcSize = 0;
nSrcSize = strlen(srcUTF8) + 1;
if (DEBUG)
{
printf("Src string length = (%d)\n", nSrcSize);
}
//Unicodeへ変換後の文字列長を得る
lengthUnicode = MultiByteToWideChar(CP_UTF8, 0, srcUTF8, nSrcSize, NULL, 0);
if (lengthUnicode <= 0)
{
if (DEBUG)
{
printf("Unicode length = (%d)\n", lengthUnicode);
}
dwErr = GetLastError();
return dwErr;
}
//必要な分だけUnicode文字列のバッファを確保
bufUnicode = malloc(sizeof(wchar_t)*lengthUnicode + 2);
//UTF8からUnicodeへ変換
nRet = MultiByteToWideChar(CP_UTF8, 0, srcUTF8, nSrcSize, bufUnicode, lengthUnicode);
if (nRet <= 0)
{
if (DEBUG)
{
printf("UTF8->Unicode length = (%d)\n", nRet);
}
free(bufUnicode);
dwErr = GetLastError();
return dwErr;
}
//ShiftJISへ変換後の文字列長を得る
lengthSJis = WideCharToMultiByte(CP_THREAD_ACP, 0, bufUnicode, lengthUnicode + 2, NULL, 0, NULL, NULL);
if (lengthSJis <= 0)
{
if (DEBUG)
{
printf("Shift Jis length = (%d)\n", lengthSJis);
}
free(bufUnicode);
dwErr = GetLastError();
return dwErr;
}
//必要な分だけShiftJIS文字列のバッファを確保
bufShiftJis = malloc(sizeof(char)*lengthSJis);
//UnicodeからShiftJISへ変換
nRet = WideCharToMultiByte(CP_THREAD_ACP, 0, bufUnicode, lengthUnicode, bufShiftJis, lengthSJis, NULL, NULL);
if (nRet <= 0)
{
if (DEBUG)
{
printf("Unicode->Shift Jis length = (%d)\n", nRet);
}
free(bufUnicode);
free(bufShiftJis);
dwErr = GetLastError();
return dwErr;
}
memcpy(dstSjis, bufShiftJis, lengthSJis);
free(bufUnicode);
free(bufShiftJis);
return 0;
}
DWORD SjistoUTF8(char *dstUTF8, char *srcSjis)
{
int nRet = 0;
DWORD dwErr = 0;
int lengthUnicode = 0;
wchar_t* bufUnicode = NULL;
int lengthUTF8 = 0;
char* bufUTF8 = NULL;
int nSrcSize = 0;
nSrcSize = strlen(srcSjis) + 1;
if (DEBUG)
{
printf("Src string length = (%d)\n", nSrcSize);
}
//Unicodeへ変換後の文字列長を得る
lengthUnicode = MultiByteToWideChar(CP_ACP, 0, srcSjis, nSrcSize, NULL, 0);
if (lengthUnicode <= 0)
{
if (DEBUG)
{
printf("Unicode length = (%d)\n", lengthUnicode);
}
dwErr = GetLastError();
return dwErr;
}
//必要な分だけUnicode文字列のバッファを確保
bufUnicode = malloc(sizeof(wchar_t)*lengthUnicode + 2);
//ShiftJISからUnicodeへ変換
nRet = MultiByteToWideChar(CP_THREAD_ACP, 0, srcSjis, nSrcSize, bufUnicode, lengthUnicode);
if (nRet <= 0)
{
if (DEBUG)
{
printf("Shift Jis->Unicode length = (%d)\n", nRet);
}
free(bufUnicode);
dwErr = GetLastError();
return dwErr;
}
//UTF8へ変換後の文字列長を得る
lengthUTF8 = WideCharToMultiByte(CP_UTF8, 0, bufUnicode, lengthUnicode + 2, NULL, 0, NULL, NULL);
if (lengthUTF8 <= 0)
{
if (DEBUG)
{
printf("UTF8 length = (%d)\n", lengthUTF8);
}
free(bufUnicode);
dwErr = GetLastError();
return dwErr;
}
//必要な分だけUTF8文字列のバッファを確保
bufUTF8 = malloc(sizeof(char)*lengthUTF8);
//UnicodeからUTF8へ変換
nRet = WideCharToMultiByte(CP_UTF8, 0, bufUnicode, lengthUnicode, bufUTF8, lengthUTF8, NULL, NULL);
if (nRet <= 0)
{
if (DEBUG)
{
printf("Unicode->UTF8 length = (%d)\n", nRet);
}
free(bufUnicode);
free(bufUTF8);
dwErr = GetLastError();
return dwErr;
}
memcpy(dstUTF8, bufUTF8, lengthUTF8);
free(bufUnicode);
free(bufUTF8);
return 0;
}
参照:
http://www.lab.its55.com/?p=32http://sayahamitt.net/utf8%E3%81%AAstring%E5%85%A5%E3%82%8C%E3%81%9F%E3%82%89shiftjis%E3%81%AAstring%E5%87%BA%E3%81%A6%E3%81%8F%E3%82%8B%E9%96%A2%E6%95%B0%E4%BD%9C%E3%81%A3%E3%81%9F/