设为首页 加入收藏

TOP

c++转码基础(1):各种编码类型及unicode和uft-8互转(二)
2016-09-12 19:03:12 】 浏览:775
Tags:基础 各种 编码 类型 unicode uft-8 互转
码 二进制编码 I 49 01001001 t 74 01110100 ' 27 00100111 s 73 01110011 20 00100000 知 E79FA5 11100111 10011111 10100101 乎 E4B98E 11100100 10111001 10001110 日 E697A5 11100110 10010111 10100101 报 E68AA5 11100110 10001010 10100101

UTF-8和UTF-16的区别

区分UTF-8还是UTF-16的文件:文件头包含

EF BB BF    UTF-8

FE FF     UTF-16/UCS-2, little endian

FF FE     UTF-16/UCS-2, big endian

FF FE 00 00  UTF-32/UCS-4, little endian.

00 00 FE FF  UTF-32/UCS-4, big-endian.

UTF-16不需要用啥字符来做标志,所以两字节也就是2的16次能表示65536个字符.

表示一个"汉"中文字(27721(十进制)), UTF-16 是 01101100 01001001; 十六进制是 6C49

而UTF-8由于里面有额外的标志信息,所有一个字节只能表示2的7次方128个字符,两个字节只能表示2的11次方2048个字符.而三个字节能表示2的16次方,65536个字符.

所以UTF-8对"汉"的编码是 11100110 10110001 10001001(这里不关注大小端的问题,大小端不同,编码顺序不同)

由上面我们可以看出UTF-8需要判断每个字节中的开头标志信息,所以如果一当某个字节在传送过程中出错了,就会导致后面的字节也会解析出错.而UTF-16不会判断开头标志,即使错也只会错一个字符,所以容错能力强.

大小端问题:

计算机是以字节为寻址单位的,这就涉及到字(2个字节), 双字(4个字节)及其他多字节单位 在计算机内如何排布的问题, 这里无非就是2种:低字节在低地址的little-endian和高字节在低地址的big-endian.

如何区分当前系统是哪种类型的大小端? 曾经看到有经验的程序员也以当前的操作系统类型来判断, 实际上系统的大小端和你的CPU架构体系相关联, 比如说X86是小端, PowPC是大端,ARM则是可控制(默认也是小端)。

要判断当前环境是大小端实际上很简单: bool IsLittleEndian() { int i=1; return (*(char *)&i == 1); }

感觉现在大端的应用主要是网络字节序, Java内部全都是大端。

UCS2和UCS4因为都是用多字节表示一个字符,所以实际上都有大小端的问题,比如分别对应UCS2-LE和UCS2-BE,Windows上的UNICODE实际上是UCS2-LE;

UTF8因为是字节流,所以没有大小端的问题。

base64 编码:

Base64是网络上最常见的用于传输8Bit字节代码的编码方式之一,大家可以查看RFC2045~RFC2049,上面有MIME的详细规范。Base64编码可用于在HTTP环境下传递较长的标识信息。

因为,Base64将三个字节转化成四个字节,因此Base64编码后的文本,会比原文本大出三分之一左右。

举一个具体的实例,演示英语单词Man如何转成Base64编码。

Text content

M

a

n

ASCII

77

97

110

Bit pattern

0

1

0

0

1

1

0

1

0

1

1

0

0

0

0

1

0

1

1

0

1

1

1

0

Index

19

22

5

46

Base64-Encoded

T

W

F

u

第一步,"M"、"a"、"n"的ASCII值分别是77、97、110,对应的二进制值是01001101、01100001、01101110,将它们连成一个24位的二进制字符串010011010110000101101110。

第二步,将这个24位的二进制字符串分成4组,每组6个二进制位:010011、010110、000101、101110。

第三步,在每组前面加两个00,扩展成32个二进制位,即四个字节:00010011、00010110、00000101、00101110。它们的十进制值分别是19、22、5、46。

第四步,根据上表,得到每个值对应Base64编码,即T、W、F、u。

如果字节数不足三,则这样处理:

a)二个字节的情况:将这二个字节的一共16个二进制位,按照上面的规则,转成三组,最后一组除了前面加两个0以外,后面也要加两个0。这样得到一个三位的Base64编码,再在末尾补上一个"="号。

比如,"Ma"这个字符串是两个字节,可以转化成三组00010011、00010110、00010000以后,对应Base64值分别为T、W、E,再补上一个"="号,因此"Ma"的Base64编码就是TWE=。

b)一个字节的情况:将这一个字节的8个二进制位,按照上面的规则转成二组,最后一组除了前面加二个0以外,后面再加4个0。这样得到一个二位的Base64编码,再在末尾补上两个"="号。

比如,"M"这个字母是一个字节,可以转化为二组00010011、00010000,对应的Base64值分别为T、Q,再补上二个"="号,因此"M"的Base64编码就是TQ==。

实例函数:

static const uint8_t *kBase64EncodeTable = (const uint8_t *)

"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";

void base64_encode(const uint8_t *in, uint32_t len, uint8_t *buf) {

buf[0] = kBase64EncodeTable[(in[0] >> 2) & 0x3F];

if (len == 3) {

buf[1] = kBase64EncodeTable[((in[0] << 4) + (in[1] >> 4)) & 0x3f];

buf[2] = kBase64EncodeTable[((in[1] << 2) + (in[2] >> 6)) & 0x3f];

buf[3] = kBase64EncodeTable[in[2] & 0x3f];

} else if (len == 2) {

buf[1] = kBase64EncodeTable[((in[0] << 4) + (in[1] >> 4)) & 0x3f];

buf[2] = kBase64EncodeTable[(in[1] << 2) & 0x3f];

} else { // len == 1

buf[1] = kBase64EncodeTable[(in[0] << 4) & 0x3f];

}

}

static const uint8_t kBase64DecodeTable[256] ={

-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,

-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,

-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,62,-1,-1,-1,63,

52,53,54,55,56,57,58,59,60,61,-1,-1,-1,-1,-1,-1,

-1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,

15,16,17,18,19,20,21,22,23,24,25,-1,-1,-1,-1,-1,

-1,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,

41,42,43,44,45,46,47,48,49,50,51,-1,-1,-1,-1,-1,

-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,

-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,

-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,

-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,

-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,

-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,

-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,

-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,

};

void base64_decode(uint8_t *buf, uint32_t len) {

buf[0] = (kBase64DecodeTable[buf[0]] << 2) |

(kBase64DecodeTable[buf[1]] >> 4);

if (len > 2) {

buf[1] = ((kBase64DecodeTable[buf[1]] << 4) & 0xf0) |

(kBase64DecodeTable[buf[2]] >> 2);

if (len > 3) {

buf[2] = ((kBase64DecodeTable[buf[2]] << 6) & 0xc0) |

(kBase64DecodeTable[buf[3]]);

}

}

}

多字符与双字符转码函数:

在Windows上不同编码方式的相互转换可以通过WideCharToMultiByte和MutiByteToWideChar进行转码。

linux下可以用mbstowcs() ,wcstombs() 或者使用iconv库函数;

需要注意的问题:

size_t mbstow

首页 上一页 1 2 3 下一页 尾页 2/3/3
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇C++学习笔记--函数 下一篇C++ primer读书笔记第13章:拷贝..

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目