目录

1 编码    1

2 编码代码(C++)    2

3 解码代码(C++)    4

4 测试代码(VC++)    7

1 编码

UTF-7编码的规则及特点为:

1)UTF16小于等于 0x7F 的字符,采用ASCII编码;

2)UTF16大于0x7F的字符,采用Base64编码,然后在首尾分别加上+-;

3)UTF-7编码后,所有字符均小于等于 0x7F。

如字符串"A编码示例bC+123"的UTF-7编码为字符串"A+fxZ4AXk6T4s-bC+-123"。"+fxZ4AXk6T4s-"中的fxZ4AXk6T4s是"编码示例"的Base64编码;"+-"表示字符+;其余的保持不变。

以"编"为例,对Base64编码进行说明:

内容

说明

字符串

7F 16

UTF-16编码,高字节在前,16进制

0111 1111 0001 0110

UTF-16编码,高字节在前,2进制

011111 110001 011000

分组,6位一组,末尾补两个0

31 49 24

10进制

f x Y

根据10进制查下面的Base64编码表

下表是Base64编码表。

个位

十位

0

1

2

3

4

5

6

7

8

9

0

A

B

C

D

E

F

G

H

I

J

1

K

L

M

N

O

P

Q

R

S

T

2

U

V

W

X

Y

Z

a

b

c

d

3

e

f

g

h

i

j

k

l

m

n

4

o

p

q

r

s

t

u

v

w

x

5

y

z

0

1

2

3

4

5

6

7

6

8

9

+

/

           

上面"编"的Base64编码是"fxY",为什么"编码示例"的Base64编码是"fxZ4AXk6T4s"呢?因为fxZ中的Z既包含了"编"的编码信息,又包含了"码"的编码信息。这是UTF-7编码最复杂的地方。

2 编码代码(C++)

//Base64 编码字符串

const static char* s_Base64Table = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";

static void UTF16to7(std::string&s7,int&n,unsigned short code[8])

{

switch(n)

{

case 1://连续 1 个字符大于 7F

n = 3; //3 个 code[]

break;

case 2://连续 2 个字符大于 7F

n = 6; //6 个 code[]

break;

case 3://连续 3 个字符大于 7F

n = 8; //8 个 code[]

break;

default:

n = 0;

}

if(n)

{

for(int i = 0;i < n;++i)

{

s7 += s_Base64Table[code[i]];

}

n = 0;

}

}

/***************************************************************\

将 UTF-16 字符串转换为 UTF-7 字符串

pUTF16 [in] UTF-16 字符串首地址

nBytes [in] UTF-16 字符串字节数,即字符数 * 2

bLE [in] UTF-16 是否低位字节在前

返回:UTF-7 字符串

\***************************************************************/

std::string UTF16toUTF7(const void*pUTF16,unsigned long nBytes,bool bLE)

{

std::string s7;

if(pUTF16 && nBytes >= 2)

{

unsigned char* p16 = (unsigned char*)pUTF16;

unsigned short u16 = 0;

bool bCode = false; //是否正在编码

//编码的第几个字符 1、2、3、1、2、3……

int n = 0;

unsigned short code[8]; //编码的内容暂时存入此数组

for(unsigned long i = 1;i < nBytes;i += 2)

{

//计算当前字符 u16

if(bLE)

{//低位字节在前

u16 = p16[i - 1] | (p16[i] << 8);

}

else

{//高位字节在前

u16 = (p16[i - 1] << 8) | p16[i];

}

if(u16 <= 0x7F)

{//当前字符小于等于 7F

if(bCode)

{

if(n)

{

UTF16to7(s7,n,code);

}

s7 += '-';

bCode = false; //标记未在编码

}

s7 += (char)u16;

if(u16 == '+')

{

s7 += '-';

}

}

else

{//当前字符大于 7F

switch(++n)

{

case 1: //连续 1 个字符大于 7F

if(!bCode)

{//编码的第一个字符

s7 += '+';

}

code[0] = u16 >> 10;

code[1] = (u16 >> 4) & 63;

code[2] = (u16 << 2) & 63;

break;

case 2: //连续 2 个字符大于 7F

code[2] |= u16 >> 14;

code[3] = (u16 >> 8) & 63;

code[4] = (u16 >> 2) & 63;

code[5] = (u16 << 4) & 63;

break;

case 3: //连续 3 个字符大于 7F

code[5] |= u16 >> 12;

code[6] = (u16 >> 6) & 63;

code[7] = u16 & 63;

//每编码 3 个字符,将 code[8] 的内容加入 s7。同时 n 重新计数

UTF16to7(s7,n,code);

break;

}

bCode = true; //标记正在编码

}

}

if(bCode)

{

if(n)

{

UTF16to7(s7,n,code);

}

s7 += '-';

}

}

return s7;

}

3 解码代码(C++)

//判断某个字符是否为 Base64 编码,出错返回 0xFF

static char IsBase64Char(char c)

{

if(c)

{

const char*pFind = strchr(s_Base64Table,c);

if(pFind)

{

return pFind - s_Base64Table;

}

}

return '\xFF';

}

static void UTF7to16(std::string&s16,unsigned short c,bool bLE)

{

if(bLE)

{//低位字节在前

s16 += (char)c;

s16 += (char)(c >> 8);

}

else

{//高位字节在前

s16 += (char)(c >> 8);

s16 += (char)c;

}

}

/***************************************************************\

将 UTF-7 字符串转换为 UTF-16 字符串

pUTF7 [in] UTF-7 字符串首地址

nBytes [in] UTF-7 字符串字节数,即字符数 * 2

bLE [in] UTF-16 是否低位字节在前

返回:UTF-16 字符串

\***************************************************************/

std::string UTF7toUTF16(const void*pUTF7

,unsigned long nBytes,bool bLE)

{

std::string s16;

if(pUTF7 && nBytes)

{

unsigned char* p7 = (unsigned char*)pUTF7;

bool bCode = false; //是否正在解码状态

int n = 0; //解码的第几个字符,[0,7] 循环

unsigned short code[8]; //解码的结果暂时存入该数组

for(unsigned long i = 0;i < nBytes;++i)

{

if(bCode)

{//正在解码状态

if(p7[i] == '-')

{//停止解码

if(p7[i - 1] == '+')

{

UTF7to16(s16,'+',bLE);

}

bCode = false;

}

else

{

code[n] = IsBase64Char(p7[i]);

if(code[n] != 0xFF)

{

switch(++n)

{

case 3://1个字符

UTF7to16(s16

,(code[0] << 10) | (code[1] << 4) | (code[2] >> 2),bLE);

break;

case 6://2个字符

UTF7to16(s16

,(code[2] << 14) | (code[3] << 8) | (code[4] << 2) | (code[5] >> 4)

,bLE);

break;

case 8://3个字符

UTF7to16(s16

,(code[5] << 12) | (code[6] << 6) | code[7],bLE);

n = 0;

break;

}

}

}

}

else

{//不在解码状态

if(p7[i] == '+')

{//当前字符为 + 号

n = 0;

bCode = true; //标记处于解码状态

}

else

{

UTF7to16(s16,p7[i],bLE);

}

}

}

}

return s16;

}

4 测试代码(VC++)

const wchar_t* pUTF16LE = L"A编码示例bC+123";

//UTF16LE 转换为 UTF7,应返回A+fxZ4AXk6T4s-bC+-123

std::string sUTF7 = UTF16toUTF7(pUTF16LE,wcslen(pUTF16LE) * 2);

//UTF7 转换为 UTF16LE

std::string sUTF16LE = UTF7toUTF16(sUTF7.c_str(),sUTF7.length());

sUTF16LE += '\0'; //末尾添加一个 \0

//pUTF16LE 所指向的宽字符串,应该是"A编码示例bC+123"

pUTF16LE = (const wchar_t*)sUTF16LE.c_str();

UTF-7编码的更多相关文章

  1. 从Java String实例来理解ANSI、Unicode、BMP、UTF等编码概念

    转(http://www.codeceo.com/article/java-string-ansi-unicode-bmp-utf.html#0-tsina-1-10971-397232819ff9a ...

  2. 文字编码ASCII,GB2312,GBK,GB18030,UNICODE,UCS,UTF的解析

    众所周知,一个文字从输入到显示到存储是有一个固定过程的,其过程为:输入码(根据输入法不同而不同)→机内码(根据语言环境不同而不同,不同的系统语言编码也不一样)→字型码(根据不同的字体而不同)→存储码( ...

  3. 字符集、字符编码、国际化、本地化简要总结(UNICODE/UTF/ASCII/GB2312/GBK/GB18030)

    PS:要转载请注明出处,本人版权所有. PS: 这个只是基于<我自己>的理解, 如果和你的原则及想法相冲突,请谅解,勿喷. 环境说明   普通的linux 和 普通的windows.    ...

  4. Python里的编码问题

    马克一篇 http://bbs.chinaunix.net/archiver/tid-1163613.html http://www.openhome.cc/Gossip/Python/ImportI ...

  5. JAVA基础学习day22--IO流四-对象序列化、管道流、RandomAccessFile、DataStream、ByteArrayStream、转换流的字符编码

    一.对象序列化 1.1.对象序列化 被操作的对象需要实现Serializable接口 1.2.对象序列化流ObjectOutputStream与ObjectInputStream ObjectInpu ...

  6. Java中常用的字符编码-解析

    ASCII字符编码 美国信息互换标准代码,为罗马字母编制的一套编码,主要用于表达现代英语和其他西欧语言中的字符,1字节的7位表示一个字符. ISO-8859-1字符编码 ISO为西欧语言中的字符制定的 ...

  7. 请问什么是UTF字符串?

    utf是编码方式,一般而言是国际性质的编码格式,有utf-8,utf-9,utf-16等多种形式,是最高级别的编码方式,也就是说如果你要读取的数据流设置成utf编码的话就要用到相应的编码方式来读取了, ...

  8. python之路--day6--字符编码

    一.知识储备 cpu--控制和运算 内存--暂时存储cpu需要的数据 硬盘--永久保存数据2.文本编辑器的原理存储原理 1,启动文本编辑器 2,在编辑器上输入内容---此时输入内容还在内存上 3,保存 ...

  9. 关于烦躁的网页编码问题utf-8,gb2312。终于自己实践了一遍

    俗话说实践是检验真理的唯一标准,的确如此. 自己一直比较懒,虽然觉得大牛应该一个记事本全部搞定,但自己还是喜欢用Dw或者Vs写好网页的架构,因为总觉得用notepad还要自己导入声明,而gVim还没有 ...

  10. Unicode字符集和UTF-8, UTF-16, UTF-32编码

    ASCII 在过去的计算中,ASCII码被用来表示字符.英语只有26个字母和其他一些特殊字符和符号. 下表提供了ASCII字符及其相应的十进制和十六进制值. 可以从上面的表中推断,在十进制数系统中,A ...

随机推荐

  1. c#调用cmd的ping命令

    private static string CmdPing(string strIp) { Process p = new Process(); p.StartInfo.FileName = &quo ...

  2. JAVA程序的创建与编辑

    1.JAVA项目的创建与命令编辑 打开JAVA程序,选择工具栏上的创建按钮旁边的小三角,在下拉菜单中选择创建JAVA项目,在出现的对话窗口中输入项目名,在JRE使用执行环境中选择可用的资源包,如果安装 ...

  3. 未能加载文件或程序集“CefSharp, Version=1.25.XXXX”或它的某一个依赖项。试图加载格式不正确的程序。

    在使用CefSharp的过程中遇到一个坑爹的错误. 从GitHub的项目主页:https://github.com/cefsharp/CefSharp/wiki/Frequently-asked-qu ...

  4. java 导出Excel 大数据量,自己经验总结!

    出处: http://lyjilu.iteye.com/ 分析导出实现代码,XLSX支持: /** * 生成<span style="white-space: normal; back ...

  5. UML分析与设计

    考点: 掌握面向对象的分析与设计 掌握UML描述方法 用例图.类图.序列图.状态转换图 类图:类的属性.方法的识别:类间的各种关系 类图:实体.联系 各种关系图例: 泛化:取公共属性 关联分为聚合.组 ...

  6. Web项目中创建简单的错误处理页面

    当应用程序出现错误的时候,如果没有做错误页面处理的话,会直接输出一些敏感的信息出来,有时候甚至会直接将项目所在的物理路径给显示出来,严重缺乏安全性,并且错误种类繁多,页面风格不一,导致用户体验不好,本 ...

  7. 最大后验估计 -- Maximum-a-Posteriori (MAP) Estimation

    最大后验估计是根据经验数据获得对难以观察的量的点估计.与最大似然估计类似,但是最大的不同时,最大后验估计的融入了要估计量的先验分布在其中.故最大后验估计可以看做规则化的最大似然估计.

  8. Codeforces Round #272 (Div. 2) C. Dreamoon and Sums 数学

    C. Dreamoon and Sums time limit per test 1.5 seconds memory limit per test 256 megabytes input stand ...

  9. Android学习参考2

    一名自学成才的Android开发者怒答! 1. Google做开发前完全是小白,真心不知道有Google这东西,只晓得百 度,遇到问题直接百度,不是黑百度,百度在娱乐八卦方面确实靠谱,但是技术方面查出 ...

  10. phpcms 头部搜索栏上边的 “新闻 | 图片 | 下载 | 专题” 是在哪里修改的?

    phpcms 是怎么修改以下 栏目列. 在后台的时候,“模块管理>全站搜索”,可以修改搜索分类