字符转换wchar

iOS和Android,Linux这类的wchar都是占4个字节的;

前提:给一个GB2312的char*,转换成wchar,用于后续其他API的使用;

步骤:char* 原始的编码格式转换成UTF8;UTF8转成UTF16、32

方法1:

char* pString= @"hcwhf2o3840932ri09fj0中文 ";

        wchar_t* pWch = NULL;
       
        {
            NSStringEncoding enc = CFStringConvertEncodingToNSStringEncoding (kCFStringEncodingGB_18030_2000);

            NSString* str = [[NSString alloc]initWithBytes:pString length:strlen(pString) encoding:enc ];
          
            const char * pos =[str UTF8String];
            ChartoWchar((char*)pos, &pWch);
        }


int ChartoWchar(char *pCha, wchar_t **pWCha)
{int nChLen  = (int)strlen(pCha);//unsigned long
    
    NSString *strutf8 = [[NSString alloc] initWithBytes:pCha length:nChLen encoding:NSUTF8StringEncoding];
    
    *pWCha = (wchar_t*)[strutf8 cStringUsingEncoding:NSUTF32StringEncoding];//ios wchar 4个字节
    
    [strutf8 release];
    
    return 1;
}
//需要做一些释放;或者自动释放之类的 

 

 方法2

              wchar_t WChar[200];
              char  convOUT[200];
              memset(WChar, 0, 200);
              memset(convOUT, 0, 200);
              char *pString = "wvsazhong中英文";

            iconv_t cd = iconv_open("utf-8", "gb2312");//打开转换器,指定从gb2312转到utf-8
            convFun(cd, pString,(int)strlen(pString),convOUT,200);//做转换
            iconv_close(cd);
            ChartoWchar(convOUT, WChar);//utf-8转utf32


int conFun(void* cd, char *ssin ,int indatalen ,char *outbuf, int outdatalen) { /*char* inbuf =ssin;//使用&inbuf
char* outbuff = outbuf;//使用&outbuff 没有卵用,ssin ,outbuf地址在iconv后还是会被改变*/
 memset(outbuf,0,outdatalen);
return iconv((iconv_t)cd, &ssin, (size_t *)&indatalen,&outbuf,(size_t *)&outdatalen);//iconv有一个特性运行完会改变输入输出buffer的地址,这里也是出现“使用已经freebuff”崩溃的一个点;这里直接用或者借助中间变量都不行,地址还是会改变,所以最好就不要接口化;这个函数运行完还会篡改附近的内存的内容
}

int ChartoWchar(char *pCha, wchar_t *pWCha)
{
   int nCharLen  = strlen(pCha);

    mbstowcs(pWCha, pCha, nCharLen);

    return 0;
}

iconv的使用:
iconv_tcd=iconv_open("GBK","UTF-8");
char*outbuf=(char*)malloc(inlen*4);
bzero(outbuf,inlen*4);
char*in=inbuf;
char*out=outbuf;
size_toutlen=inlen*4;
iconv(cd,&in,(size_t*)&inlen,&out,&outlen);
outlen=strlen(outbuf);
printf("%s\n",outbuf);
free(outbuf);
iconv_close(cd);
非常值得注意的地方是:iconv函数会修改参数in和参数out指针所指向的地方,也就是说,在调用iconv函数之前,我们的in和inbuf指针以及out和outbuf指针指向的是同一块内存区域,但是调用之后out指针所指向的地方就不是outbuf了,同理in指针。所以要
char*in=inbuf;char*out=outbuf;
另存一下,使用或者释放内存的时候也要使用原先的那个指针outbuf和inbuf。

 

 

 这是一个传值问题;导致的;以至于影响了后边对相关内存操作;会崩溃

malloc: *** set a breakpoint in malloc_error_break to debug

malloc: Incorrect checksum for freed object 0x1471d1000: probably modified after being freed.

Corrupt value: 0x0

 

 

 方法3:

windows:映射一个字符串到一个宽字符(unicode)的字符串

用到的是MultiByteToWideChar (CP_ACP、CP_OEMCP)

CP_ACP:ANSI字符集;                              CP_MACCP:Macintosh代码页;                 CP_OEMCP:OEM代码页;
CP_SYMBOL:符号字符集(42);                   CP_THREAD_ACP:当前线程ANSI代码页;
CP_UTF7:使用UTF-7转换;                            CP_UTF8:使用UTF-8转换。
 
    原始字符中含有中文简体 繁体;注意使用的代码页会有所不同
    MultiByteToWideChar  :https://www.cnblogs.com/mugua/archive/2009/03/17/1414505.html
    第一个参数为代码页, 用 GetLocaleInfo 函数获取当前系统的代码页,936: 简体中文, 950: 繁体中文 
    第二个参数为选项,一般用 0 就可以了 
    第三个参数为 ANSI 字符串的地址, 这个字符串是第一个参数指定的语言的 ANSI 字符串 (AnsiString) 
    第四个参数为 ANSI 字符串的长度,如果用 -1, 就表示是用 0 作为结束符的字符串 
    第五个参数为转化生成的 unicode 字符串 (WideString) 的地址, 如果为 NULL, 就是代表计算生成的字符串的长度 
    第六个参数为转化生成的 unicode 字符串缓存的容量
 

方法四 utf8-utf32:跨平台

ChartoWchar使用mbstowcs适用于除了Linux,Android,但是在IOS平台文字中有中文就转换不了了
所以就要用到下边的代码:IOS wchar_t占4字节

一般IOS平台送来的文字是GB2312;先转换成UTF8:iconv_open("utf-8", "gb2312"); iconv;在转换成wchar的时候可以使用

[[NSString alloc] initWithBytes:str  length:len  encoding:NSUTF8StringEncoding];
(wchar_t*)[str_NSString  cStringUsingEncoding:NSUTF32StringEncoding];

但是这个不是跨平台的,可能initWithBytes在C++中使用还有内存泄漏,你要是ARC 还不能调用delete和release

size_t convU8toU32(const UInt8* src, UInt32* des)   
{
       
size_t number = 0; while(*src) { UInt32 tmp; size_t len = change(src, tmp); if (len == 0) break; if (des) { (*des) = tmp; ++des; } src += len; number += 1; } if (des) (*des) = 0; return number; }
int change(const UInt8* src, UInt32& des)
{
        if (!src)
return 0; UInt8 b = *(src++); if (b < 0x80) { des = b; return 1; } if (b < 0xC0 || b > 0xFD)
return 0;
int len; if (b < 0xE0) { des = b & 0x1F; len = 2; } else if (b < 0xF0) { des = b & 0x0F; len = 3; } else if (b < 0xF8) { des = b & 0x07; len = 4; } else if (b < 0xFC) { des = b & 0x03; len = 5; } else { des = b & 0x01; len = 6; } size_t i = 1; for (; i < len; ++i) { b = *(src++); if (b < 0x80 || b > 0xBF) return 0; des = (des << 6) + (b & 0x3F); } return len; }

 



 

转自:秦建辉
https://blog.csdn.net/jhqin/article/details/5687505
#include "UnicodeConverter.h"

/* -------------------------------------------------------------
					内码转换
   ------------------------------------------------------------- */

// 转换UCS4编码到UTF8编码
INT CUnicodeConverter::UCS4_To_UTF8( DWORD dwUCS4, BYTE* pbUTF8 )
{
	const BYTE	abPrefix[] = {0, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC};
	const DWORD adwCodeUp[] = {
		0x80,			// U+00000000 ~ U+0000007F
		0x800,			// U+00000080 ~ U+000007FF
		0x10000,		// U+00000800 ~ U+0000FFFF
		0x200000,		// U+00010000 ~ U+001FFFFF
		0x4000000,		// U+00200000 ~ U+03FFFFFF
		0x80000000		// U+04000000 ~ U+7FFFFFFF
	};

	INT	i, iLen;

	// 根据UCS4编码范围确定对应的UTF-8编码字节数
	iLen = sizeof(adwCodeUp) / sizeof(DWORD);
	for( i = 0; i < iLen; i++ )
	{
		if( dwUCS4 < adwCodeUp[i] )
		{
			break;
		}
	}

	if( i == iLen )return 0;	// 无效的UCS4编码
		
	iLen = i + 1;	// UTF-8编码字节数
	if( pbUTF8 != NULL )
	{	// 转换为UTF-8编码
		for( ; i > 0; i-- )
		{
			pbUTF8[i] = static_cast<BYTE>((dwUCS4 & 0x3F) | 0x80);
			dwUCS4 >>= 6;
		}

		pbUTF8[0] = static_cast<BYTE>(dwUCS4 | abPrefix[iLen - 1]);
	}

	return iLen;
}

// 转换UTF8编码到UCS4编码
INT CUnicodeConverter::UTF8_To_UCS4( const BYTE* pbUTF8, DWORD& dwUCS4 )
{
	INT		i, iLen;
	BYTE	b;

	if( pbUTF8 == NULL )
	{	// 参数错误
		return 0;
	}

	b = *pbUTF8++;
	if( b < 0x80 )
	{
		dwUCS4 = b;
		return 1;
	}

	if( b < 0xC0 || b > 0xFD )
	{	// 非法UTF8
		return 0; 
	}

	if( b < 0xE0 )
	{
		dwUCS4 = b & 0x1F;
		iLen = 2;
	}
	else if( b < 0xF0 )
	{
		dwUCS4 = b & 0x0F;
		iLen = 3;
	}
	else if( b < 0xF8 )
	{
		dwUCS4 = b & 7;
		iLen = 4;
	}
	else if( b < 0xFC )
	{
		dwUCS4 = b & 3;
		iLen = 5;
	}
	else
	{
		dwUCS4 = b & 1;
		iLen = 6;
	}

	for( i = 1; i < iLen; i++ )
	{
		b = *pbUTF8++;
		if( b < 0x80 || b > 0xBF )
		{	// 非法UTF8
			break;
		}

		dwUCS4 = (dwUCS4 << 6) + (b & 0x3F);
	}

	if( i < iLen )
	{	// 非法UTF8
		return 0;
	}
	else
	{
		return iLen;
	}
}

// 转换UCS4编码到UCS2编码
INT CUnicodeConverter::UCS4_To_UTF16( DWORD dwUCS4, WORD* pwUTF16 )
{
	if( dwUCS4 <= 0xFFFF )
	{
		if( pwUTF16 != NULL )
		{
			*pwUTF16 = static_cast<WORD>(dwUCS4);
		}

		return 1;
	}
	else if( dwUCS4 <= 0xEFFFF )
	{
		if( pwUTF16 != NULL )
		{
			pwUTF16[0] = static_cast<WORD>( 0xD800 + (dwUCS4 >> 10) - 0x40 );	// 高10位
			pwUTF16[1] = static_cast<WORD>( 0xDC00 + (dwUCS4 & 0x03FF) );		// 低10位
		}

		return 2;
	}
	else
	{
		return 0;
	}
}

// 转换UCS2编码到UCS4编码
INT CUnicodeConverter::UTF16_To_UCS4( const WORD* pwUTF16, DWORD& dwUCS4 )
{
	WORD	w1, w2;

	if( pwUTF16 == NULL )
	{	// 参数错误
		return 0;
	}

	w1 = pwUTF16[0];
	if( w1 >= 0xD800 && w1 <= 0xDFFF )
	{	// 编码在替代区域(Surrogate Area)
		if( w1 < 0xDC00 )
		{
			w2 = pwUTF16[1];
			if( w2 >= 0xDC00 && w2 <= 0xDFFF )
			{
				dwUCS4 = (w2 & 0x03FF) + (((w1 & 0x03FF) + 0x40) << 10);
				return 2;
			}
		}

		return 0;	// 非法UTF16编码	
	}
	else
	{
		dwUCS4 = w1;
		return 1;
	}
}

// 转换UTF8字符串到UTF16字符串
INT CUnicodeConverter::UTF8Str_To_UTF16Str( const BYTE* pbszUTF8Str, WORD* pwszUTF16Str )
{
	INT		iNum, iLen;
	DWORD	dwUCS4;

	if( pbszUTF8Str == NULL )
	{	// 参数错误
		return 0;
	}

	iNum = 0;	// 统计有效字符个数
	while( *pbszUTF8Str )
	{	// UTF8编码转换为UCS4编码
		iLen = UTF8_To_UCS4( pbszUTF8Str, dwUCS4 );
		if( iLen == 0 )
		{	// 非法的UTF8编码
			return 0;
		}

		pbszUTF8Str += iLen;

		// UCS4编码转换为UTF16编码
		iLen = UCS4_To_UTF16( dwUCS4, pwszUTF16Str );
		if( iLen == 0 )
		{
			return 0;
		}

		if( pwszUTF16Str != NULL )
		{
			pwszUTF16Str += iLen;
		}
		
		iNum += iLen;
	}

	if( pwszUTF16Str != NULL )
	{
		*pwszUTF16Str = 0;	// 写入字符串结束标记
	}

	return iNum;
}

// 转换UTF16字符串到UTF8字符串
INT CUnicodeConverter::UTF16Str_To_UTF8Str( const WORD* pwszUTF16Str, BYTE* pbszUTF8Str )
{
	INT		iNum, iLen;
	DWORD	dwUCS4;

	if( pwszUTF16Str == NULL )
	{	// 参数错误
		return 0;
	}

	iNum = 0;
	while( *pwszUTF16Str )
	{	// UTF16编码转换为UCS4编码
		iLen = UTF16_To_UCS4( pwszUTF16Str, dwUCS4 );
		if( iLen == 0 )
		{	// 非法的UTF16编码
			return 0;	
		}
		
		pwszUTF16Str += iLen;

		// UCS4编码转换为UTF8编码
		iLen = UCS4_To_UTF8( dwUCS4, pbszUTF8Str );
		if( iLen == 0 )
		{
			return 0;
		}

		if( pbszUTF8Str != NULL )
		{
			pbszUTF8Str += iLen;
		}
		
		iNum += iLen;
	}

	if( pbszUTF8Str != NULL )
	{
		*pbszUTF8Str = 0;	// 写入字符串结束标记
	}

	return iNum;
}

/* -------------------------------------------------------------
					C文件写入操作
   ------------------------------------------------------------- */

// 向文件中输出UTF8编码
UINT CUnicodeConverter::Print_UTF8_By_UCS4( FILE* out, DWORD dwUCS4 )
{
	INT		iLen;
	BYTE	abUTF8[8];

	if( out == NULL )
	{
		return 0;
	}

	iLen = UCS4_To_UTF8( dwUCS4, abUTF8 );
	if( iLen == 0 )return 0;

	fwrite( abUTF8, 1, iLen, out );

	return iLen;
}

// 向文件中输出UTF16编码
UINT CUnicodeConverter::Print_UTF16_By_UCS4( FILE* out, DWORD dwUCS4, BOOL isBigEndian )
{
	INT		i, iLen;
	WORD	wCode, awUTF16[2];

	if( out == NULL )
	{
		return 0;
	}

	iLen = UCS4_To_UTF16( dwUCS4, awUTF16 );
	if( iLen == 0 )return 0;

	for( i = 0; i < iLen; i++ )
	{
		wCode = awUTF16[i];
		if( isBigEndian )
		{
			fputc( wCode >> 8, out );	// 输出高位
			fputc( wCode & 0xFF, out );	// 输出低位
		}
		else
		{
			fputc( wCode & 0xFF, out );	// 输出低位
			fputc( wCode >> 8, out );	// 输出高位
		}
	}

	return (iLen << 1);
}

// 将UTF16字符串以UTF8编码输出到文件中
UINT CUnicodeConverter::Print_UTF8Str_By_UTF16Str( FILE* out, const WORD* pwszUTF16Str )
{
	INT		iCount, iLen;
	DWORD	dwUCS4;

	if( (out == NULL) || (pwszUTF16Str == NULL) )
	{
		return 0;
	}

	iCount = 0;
	while( *pwszUTF16Str )
	{	// 将UTF16编码转换成UCS4编码
		iLen = UTF16_To_UCS4( pwszUTF16Str, dwUCS4 );
		if( iLen == 0 )
		{
			break;
		}

		pwszUTF16Str += iLen;

		// 向文件中输出UTF8编码
		iCount += Print_UTF8_By_UCS4( out, dwUCS4 );
	}

	return iCount;	// 输出的字节数
}

// 将UTF8字符串以UTF16编码输出到文件中
UINT CUnicodeConverter::Print_UTF16Str_By_UTF8Str( FILE* out, const BYTE* pbszUTF8Str, BOOL isBigEndian )
{
	INT		iCount, iLen;
	DWORD	dwUCS4;

	if( (out == NULL) || (pbszUTF8Str == NULL) )
	{
		return 0;
	}

	iCount = 0;
	while( *pbszUTF8Str )
	{	// 将UTF16编码转换成UCS4编码
		iLen = UTF8_To_UCS4( pbszUTF8Str, dwUCS4 );
		if( iLen == 0 )
		{
			break;
		}

		pbszUTF8Str += iLen;

		// 向文件中输出UTF8编码
		iCount += Print_UTF16_By_UCS4( out, dwUCS4, isBigEndian );
	}

	return iCount;	// 输出的字节数
}

// 向文件中输出UTF8字节序标记
UINT CUnicodeConverter::Print_UTF8_BOM( FILE* out )
{
	if( out == NULL )
	{
		return 0;
	}

	fputc( 0xEF, out );
	fputc( 0xBB, out );
	fputc( 0xBF, out );

	return 3;
}

// 向文件中输出UTF16字节序标记
UINT CUnicodeConverter::Print_UTF16_BOM( FILE* out, BOOL isBigEndian )
{
	if( out == NULL )
	{
		return 0;
	}

	if( isBigEndian )
	{
		fputc( 0xFE, out );
		fputc( 0xFF, out );
	}
	else
	{
		fputc( 0xFF, out );
		fputc( 0xFE, out );
	}

	return 2;
}

/* -------------------------------------------------------------
					C++流输出操作
   ------------------------------------------------------------- */

// 向流中输出UTF8编码
UINT CUnicodeConverter::Print_UTF8_By_UCS4( ostream& os, DWORD dwUCS4 )
{
	INT		iLen;
	BYTE	abUTF8[8];

	if( !os )return 0;
	
	iLen = UCS4_To_UTF8( dwUCS4, abUTF8 );
	if( iLen == 0 )return 0;

	os.write( reinterpret_cast<CHAR*>(abUTF8), iLen );

	return iLen;	
}

// 向流中输出UTF16编码
UINT CUnicodeConverter::Print_UTF16_By_UCS4( ostream& os, DWORD dwUCS4, BOOL isBigEndian )
{
	INT		i, iLen;
	WORD	wCode, awUTF16[2];

	if( !os )return 0;
	
	iLen = UCS4_To_UTF16( dwUCS4, awUTF16 );
	if( iLen == 0 )return 0;

	for( i = 0; i < iLen; i++ )
	{
		wCode = awUTF16[i];
		if( isBigEndian )
		{
			os.put( wCode >> 8 );		// 输出高位
			os.put( wCode & 0xFF );		// 输出低位
		}
		else
		{
			os.put( wCode & 0xFF );		// 输出低位
			os.put( wCode >> 8 );		// 输出高位
		}
	}

	return (iLen << 1);
}

// 将UTF16字符串以UTF8编码输出到流中
UINT CUnicodeConverter::Print_UTF8Str_By_UTF16Str( ostream& os, const WORD* pwszUTF16Str )
{
	INT		iCount, iLen;
	DWORD	dwUCS4;

	if( !os || (pwszUTF16Str == NULL) )return 0;
	
	iCount = 0;
	while( *pwszUTF16Str )
	{	// 将UTF16编码转换成UCS4编码
		iLen = UTF16_To_UCS4( pwszUTF16Str, dwUCS4 );
		if( iLen == 0 )
		{
			break;
		}

		pwszUTF16Str += iLen;

		// 向流中输出UTF8编码
		iCount += Print_UTF8_By_UCS4( os, dwUCS4 );
	}

	return iCount;	// 输出的字节数
}

// 将UTF8字符串以UTF16编码输出到流中
UINT CUnicodeConverter::Print_UTF16Str_By_UTF8Str( ostream& os, const BYTE* pbszUTF8Str, BOOL isBigEndian )
{
	INT		iCount, iLen;
	DWORD	dwUCS4;

	if( !os || (pbszUTF8Str == NULL) )return 0;

	iCount = 0;
	while( *pbszUTF8Str )
	{	// 将UTF16编码转换成UCS4编码
		iLen = UTF8_To_UCS4( pbszUTF8Str, dwUCS4 );
		if( iLen == 0 )
		{
			break;
		}

		pbszUTF8Str += iLen;

		// 向流中输出UTF8编码
		iCount += Print_UTF16_By_UCS4( os, dwUCS4, isBigEndian );
	}

	return iCount;	// 输出的字节数
}

// 向流中输出UTF8字节序标记
UINT CUnicodeConverter::Print_UTF8_BOM( ostream& os )
{
	if( !os )return 0;
	
	os.put( 0xEF );
	os.put( 0xBB );
	os.put( 0xBF );

	return 3;	
}

// 向流中输出UTF16字节序标记
UINT CUnicodeConverter::Print_UTF16_BOM( ostream& os, BOOL isBigEndian )
{
	if( !os )return 0;
	
	if( isBigEndian )
	{
		os.put( 0xFE );
		os.put( 0xFF );
	}
	else
	{
		os.put( 0xFF );
		os.put( 0xFE );
	}

	return 2;
}

/* ------------------------------
				END
   ------------------------------ */

 

posted on 2021-11-03 20:32  邗影  阅读(415)  评论(0编辑  收藏  举报

导航