字符集与字符编码


ANSI多字节字符集

最初,Internet上只有一种字符集——ANSI(American National Standard Institute)的ASCII(American Standard Code for Information Interchange)字符集。

后来,不同的国家和地区制定了不同的标准,由此产生了 GB2312、GBK、GB18030、Big5、Shift_JIS 等各自的编码标准。这些使用多个字节来代表一个字符的各种汉字延伸编码方式,称为 ANSI 编码。从ANSI标准派生的字符集被习惯的统称为ANSI字符集,它们正式的名称应该是MBCS(Multi-Byte Chactacter System,即多字节字符系统)。

由字节数据的最高位判断:

  • 最高位为0,代表是单字节,按照ASCII表进行编码
    ASCII编码是用一个字节(8bit)表示的字符编码,其中只用到了7位,表示127个字符。
  • 最高位为1,代表是本地化扩展字符,需要将相邻的两个字节组成一个整体,来进行码值求取,得到的码值对应的本地化字符集中可以得到相应的字符是什么。
    • 简体中文系统下,ANSI编码代表GB2312编码(GBK是GB2312的扩展,兼容GB2312)
    • 繁体中文系统下,ANSI编码代表BIG5编码
    • 日文系统下,ANSI编码代表JIS编码

不同ANSI编码之间互不兼容,当信息在国际间交流时,无法将属于两种语言的文字,存储在同一段ANSI编码的文本中。需要将不同的ANSI编码都转换成UTF-8编码,进而存储。

Unicode字符集

Unicode即Universal Multiple-Octet Coded Character Set,通用多八位编码字符集。
国际组织制定的可以容纳世界上所有文字和字符的编码方案,分为多个平面,一般常用0号平面也叫基本多文种平面(Basic Multilingual Plane)即Ox0000-OxFFFF来表示一个字符(对于英文浪费了一个字节)。

  • UTF-8(最主流的编码方式)
    UTF-8是Unicode的实现方式之一,是一种针对Unicode的可变长度字符编码,使用1-4个字节进行编码。
Unicode编号范围码位数UTF-8使用字节数UTF-16使用字节数二进制最大有效位数转换为字节编码
00-7F1281270xxxxxxx
80-7FF19202211110xxxxx 10xxxxxx
800-FFFF6348832161110xxxx 10xxxxxx 10xxxxxx
100000-10FFFF1048576442111110xxx 10xxxxxx 10xxxxxx 10xxxxxx
  • UTF-16
    可变长度字符编码,将字符编码成2字节或者4字节
  • UTF-32
    固定长度的编码,始终占用4字节。

Windows平台的字符转换

头文件<tchar.h>作用就是为了进行ASCII码和UNICODE(wide-character)码的头文件(该头文件由微软提供)

L指令

字符串前面加L表示该字符串是Unicode字符串,可以将ANSI字符串转换为Unicode字符串,就是每个字符占2个字节。

strlen("abc") = 3;
strlen(L"abc") = 6;

_T()宏

_T(“”)是一个宏定义在tchar.h下。

_T()或者TEXT()宏,可以把引号括起来的字符串,根据环境选择合适的编码方式。

  • 如果定义的是Unicode,那么_T(“abc”)就相当于L"abc",也就是宽字符;
  • 如果是多字节编码,那么英文采用单字节,汉字采用双字节;
  • 在Unicode环境下,要求LPCWSTR的地方不可以给一个char*,而在多字节编码下可以。

比如

wchar_t Str[] = L"Hello World!";是双字节存储字符串,_T是与之适配的宏。

当有#ifdef _UNICODE的时候,_T()就是L;

当没有#ifdef _UNICODE的时候,_T()就是ANSI的。

MFC中CString

CString实际是CStringT,也就是模板类

在Unicode环境下,实际是CStringW

在多字符集环境下,实际是CStringA

GB2312与UTF-8的转换

	char* U2G(const char* utf8)
	{
		int len = MultiByteToWideChar(CP_UTF8, 0, utf8, -1, NULL, 0);
		wchar_t* wstr = new wchar_t[len + 1];
		memset(wstr, 0, len + 1);
		MultiByteToWideChar(CP_UTF8, 0, utf8, -1, wstr, len);
		len = WideCharToMultiByte(CP_ACP, 0, wstr, -1, NULL, 0, NULL, NULL);
		char* str = new char[len + 1];
		memset(str, 0, len + 1);
		WideCharToMultiByte(CP_ACP, 0, wstr, -1, str, len, NULL, NULL);
		if (wstr) delete[] wstr;
		return str;
	}

	char* G2U(const char* gb2312)
	{
		int len = MultiByteToWideChar(CP_ACP, 0, gb2312, -1, NULL, 0);
		wchar_t* wstr = new wchar_t[len + 1];
		memset(wstr, 0, len + 1);
		MultiByteToWideChar(CP_ACP, 0, gb2312, -1, wstr, len);
		len = WideCharToMultiByte(CP_UTF8, 0, wstr, -1, NULL, 0, NULL, NULL);
		char* str = new char[len + 1];
		memset(str, 0, len + 1);
		WideCharToMultiByte(CP_UTF8, 0, wstr, -1, str, len, NULL, NULL);
		if (wstr) delete[] wstr;
		return str;
	}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值