转换编码格式(纯c语言)

windows下,用纯c语言转换编码格式。

主要用到两个windows api 函数MultiByteToWideCharWideCharToMultiByte。简单介绍这两个函数:

(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,设置此值时lpDefaultCharlpUsedDefaultChar都必须为NULL 
     CP_UTF8 UTF-8,设置此值时lpDefaultCharlpUsedDefaultChar都必须为NULL  
     

dwFlags

     指定是否转换成预制字符或合成的宽字符,对控制字符是否使用像形文字,以及怎样处理无效字符。          MB_PRECOMPOSED 总是使用预制字符,即有单个预制字符时,就不会使用分解的基字符和不占空间字符。此为函数的默认选项,不能和MB_COMPOSITE合用

         MB_COMPOSITE 总是使用分解字符,即总是使用基字符+不占空间字符的方式

         MB_ERR_INVALID_CHARS 设置此选项,函数遇到非法字符就失败并返回错误码ERROR_NO_UNICODE_TRANSLATION,否则丢弃非法字符

         MB_USEGLYPHCHARS 使用像形字符代替控制字符

  /*于下列代码页dwFlags须为0,否函数返回错误码ERROR_INVALID_FLAGS50220 50221 50222 50225 50227 50229 52936 54936 5700257011 65000(UTF7) 42(Symbol)UTF8dwFlags须为0MB_ERR_INVALID_CHARS,否函数都将失并返回错误码ERROR_INVALID_FLAGS */

 
lpMultiByteStr

                   指向将被转换字符串的字符

 
cbMultiByte

         指定由参数lpMultiByteStr指向的字符串中的个数。如果lpMultiByteStr指定的字符串以空字符终止,可以设置为-1(如果字符串不是以空字符中止,设置为-1可能失败,可能成功),此参数设置为0函数将失败

lpWideCharStr 

         指向接收被转换字符串的冲区

cchWideChar

         指定由参数lpWideCharStr指向的缓冲区的宽字符个数。若此值为零,函数返回缓冲区所必需的字符数,在这种情况下,lpWideCharStr中的缓冲区不被使用。

返回值:

  1. 如果函数运行成功,并且cchWideChar不为零,返回值是由lpWideCharStr指向的缓冲区中写入的宽字符数;
  2. 如果函数运行成功,并且cchWideChar为零,返回值是接收到待转换字符串的缓冲区所需求的宽字符数大小。
  3. 如果函数运行失败,返回值为零。若想获得更多错误信息,请调用GetLastError函数。它可以返回下面所列错误代码:

                  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。当函数返回以便检查宽字节字符串是否被成功地转换后,可以测试该变量。

返回值:

  1. 如果函数运行成功,并且cchMultiByte不为零,返回值是由 lpMultiByteStr指向的缓冲区中写入的字节数;
  2. 如果函数运行成功,并且cchMultiByte为零,返回值是接收到待转换字符串的缓冲区所必需的字节数。
  3. 如果函数运行失败,返回值为零。若想获得更多错误信息,请调用GetLastError函数。它可以返回下面所列错误代码:

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/

你可能感兴趣的:(Windows,编程)