UTF-7编码

目录

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();

时间: 2024-10-24 14:15:36

UTF-7编码的相关文章

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

众所周知,一个文字从输入到显示到存储是有一个固定过程的,其过程为:输入码(根据输入法不同而不同)→机内码(根据语言环境不同而不同,不同的系统语言编码也不一样)→字型码(根据不同的字体而不同)→存储码(根据保存的编码类型不同而不同).不同的存储码之间又有什么异同呢? 一.ASCII系列编码 首先来说明ASCII码(American Standard Code for Information Interchange,美国标准信息交换码),这个编码的时代就久远了,是由美国国家标准局(ANSI)制定,目

计算机中的编码问题

计算机中的编码问题 因为计算机只能处理数字,如果要处理文本,就必须先把文本转换为数字才能处理.最早的计算机在设计时采用8个比特(bit)作为一个字节(byte),所以,一个字节能表示的最大的整数就是255(二进制11111111=十进制255),如果要表示更大的整数,就必须用更多的字节.比如两个字节可以表示的最大整数是65535,4个字节可以表示的最大整数是4294967295. 一.目前常用的编码 ASCII编码:由于计算机是美国人发明的,因此,最早只有127个字母被编码到计算机里,也就是大小

刨根究底字符编码之二——关键术语解释(下)

关键术语解释(下) 一.第1层 抽象字符表ACR (Abstract Character Repertoire抽象字符清单):明确字符的范围(即确定支持哪些字符) 1. 抽象字符表ACR是一个编码系统支持的所有抽象字符的集合,可以简单理解为无序的字符集合,用于确定字符的范围,即要支持哪些字符. 抽象字符表ACR的一个重要特点是字符的无序性,即其中的字符并没有编排数字顺序,当然也就没有数字编号. 2. "抽象"字符不具有某种特定的字形,不应与具有某种特定字形的"具体"

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

一.对象序列化 1.1.对象序列化 被操作的对象需要实现Serializable接口 1.2.对象序列化流ObjectOutputStream与ObjectInputStream ObjectInputStream 对以前使用 ObjectOutputStream 写入的基本数据和对象进行反序列化. ObjectOutputStream 和 ObjectInputStream 分别与 FileOutputStream 和 FileInputStream 一起使用时,可以为应用程序提供对对象图形的

精述字符编码(读这篇绝对不够)

带你了解ASCII,Latin1,ANSI,Unicode,UCS-2,UCS-4,UTF-8,UTF-16,UTF-32,GB2312,GB13000,GBK,GB18030,BIG5,BOM,BMP,Littile Endian,Big Endian,内码,外码,CodePage. 1.导语 字符编码(Character Encoding)是计算机显示文本的基础,是每一位IT从业者必知的计算机基础知识点,如同数值在计算中如何存储表示,那么基础,那么重要.然因字符编码历史久远,变更频繁,地域差

html5之meta charset网页字符编码简写

html5之meta charset网页字符编码简写缩写篇教程(音乐放松椅) 除了DOCTYPE html可以在HTML5中开始可以简写,并此缩写兼容各大新旧版本和不同品牌浏览器,meta charset网页编码也可以简写缩写,同时也兼容新旧版本浏览器和不同品牌浏览器. 相关教程了解: html5 DOCTYPE简写 在HTML5提起对HTML代码优化简写缩写,同样在DIV CSS中不可缺少的charset网页编码代码也可以缩写简写(html代码优化压缩).一.utf-8编码原始代码与简化缩写

2016最新Java学习计划

一.Java学习路线图 二.Java学习路线图--视频篇 六大阶段 学完后目标 知识点 配套免费资源(视频+笔 记+源码+模板) 密码        第一阶段 Java基础 入门 学习周期: 35天 学完后目标: 1.可进行小型应用程序开发 2.对数据库进行基本的增删改查管理 市场价值:¥5000 计算机基础知识 计算机基础.DOS常用命令.Java概述.JDK环境安装配置.环境变量配置.Java程序入门 1.2015年Java基础视频-深入浅出精华版(强烈推荐) 2.历经5年锤炼(适合初学者入

开始写代码了:“Hello World”

1.先来了解一下写代码的流程1)创建xxx.py的文件 (注意文件不要以中文命名,否则导入的时候会出现不可预知的错误.)2)写代码 a.头部两行 :#!User/bin/env python                        # -*- coding:utf-8 -*- b.写功能代码3)执行代码 a.打开执行终端 (快捷键:功能键+R) b.python 代码文件路径 2.写第一个代码:hello world: >>>print("Hello World"

语言独立性和与语言无关的组件

语言独立性和与语言无关的组件 .NET Framework 4.5 .NET Framework 是独立于语言的. 这意味着,作为开发人员,您可以使用面向 .NET Framework 的多种语言(例如,C#.C++/CLI.Eiffel.F#.IronPython.IronRuby.PowerBuilder.Visual Basic.Visual COBOL 以及 Windows PowerShell)之一进行开发. 您可以访问针对 .NET Framework 开发的类库的类型和成员,而不必

[Python] 网络爬虫实战(一):网站链接的初级爬取

闲来无事,想要学习一下Python,十月初的时候搭好了ubuntu的环境,用的是Ubuntu 16.04 32位+sublime Text3,轻量级的编程环境,感觉用起来还是比较舒服的.也陆陆续续地学习了一下python的语法和相关的知识点,并没有感觉到python有什么特别的地方,数据结构中的列表,元组和字典,还没有感到其特点在哪里比较明显,只是一个数据结构而已.恰好学院老师让搜集就业相关信息,所以就想尝试去先写一个爬虫,爬一下相关网站的相关链接.先提起兴趣,再去学习枯燥的知识点. 一开始以为