UTF-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编码的更多相关文章
- 从Java String实例来理解ANSI、Unicode、BMP、UTF等编码概念
转(http://www.codeceo.com/article/java-string-ansi-unicode-bmp-utf.html#0-tsina-1-10971-397232819ff9a ...
- 文字编码ASCII,GB2312,GBK,GB18030,UNICODE,UCS,UTF的解析
众所周知,一个文字从输入到显示到存储是有一个固定过程的,其过程为:输入码(根据输入法不同而不同)→机内码(根据语言环境不同而不同,不同的系统语言编码也不一样)→字型码(根据不同的字体而不同)→存储码( ...
- 字符集、字符编码、国际化、本地化简要总结(UNICODE/UTF/ASCII/GB2312/GBK/GB18030)
PS:要转载请注明出处,本人版权所有. PS: 这个只是基于<我自己>的理解, 如果和你的原则及想法相冲突,请谅解,勿喷. 环境说明 普通的linux 和 普通的windows. ...
- Python里的编码问题
马克一篇 http://bbs.chinaunix.net/archiver/tid-1163613.html http://www.openhome.cc/Gossip/Python/ImportI ...
- JAVA基础学习day22--IO流四-对象序列化、管道流、RandomAccessFile、DataStream、ByteArrayStream、转换流的字符编码
一.对象序列化 1.1.对象序列化 被操作的对象需要实现Serializable接口 1.2.对象序列化流ObjectOutputStream与ObjectInputStream ObjectInpu ...
- Java中常用的字符编码-解析
ASCII字符编码 美国信息互换标准代码,为罗马字母编制的一套编码,主要用于表达现代英语和其他西欧语言中的字符,1字节的7位表示一个字符. ISO-8859-1字符编码 ISO为西欧语言中的字符制定的 ...
- 请问什么是UTF字符串?
utf是编码方式,一般而言是国际性质的编码格式,有utf-8,utf-9,utf-16等多种形式,是最高级别的编码方式,也就是说如果你要读取的数据流设置成utf编码的话就要用到相应的编码方式来读取了, ...
- python之路--day6--字符编码
一.知识储备 cpu--控制和运算 内存--暂时存储cpu需要的数据 硬盘--永久保存数据2.文本编辑器的原理存储原理 1,启动文本编辑器 2,在编辑器上输入内容---此时输入内容还在内存上 3,保存 ...
- 关于烦躁的网页编码问题utf-8,gb2312。终于自己实践了一遍
俗话说实践是检验真理的唯一标准,的确如此. 自己一直比较懒,虽然觉得大牛应该一个记事本全部搞定,但自己还是喜欢用Dw或者Vs写好网页的架构,因为总觉得用notepad还要自己导入声明,而gVim还没有 ...
- Unicode字符集和UTF-8, UTF-16, UTF-32编码
ASCII 在过去的计算中,ASCII码被用来表示字符.英语只有26个字母和其他一些特殊字符和符号. 下表提供了ASCII字符及其相应的十进制和十六进制值. 可以从上面的表中推断,在十进制数系统中,A ...
随机推荐
- sqlserver2008安装教程
这几天因为需要,一直想安装sql server 2008来作为Web后台的数据库进行些实验,但总是没有时间,今天终于有时间了,便安装了SQL Server 2008,以下是我的安装的步骤,希望对于有需 ...
- spark记录
Filtering multiple values in multiple columns: In the case where you're pulling data from a database ...
- PM(Project Manager):系列博客
http://blog.csdn.net/MoreeVan/article/list/2
- 数据库批量修改表名,增加前缀(SQL server)
exec sp_msforeachtable @command1=' declare @o sysname,@n sysname select @o=''?'' ,@n=stuff(@o,1,7,'' ...
- ios照片获取,拍照功能
// // HYBPhotoPickerManager.h // ehui // // Created by 黄仪标 on 14/11/26. // Copyright (c) 2014年 黄 ...
- UVA 10163 十六 Storage Keepers
十六 Storage Keepers Time Limit:3000MS Memory Limit:0KB 64bit IO Format:%lld & %llu Submit ...
- [Java解惑]数值表达式
声明:原创作品,转载时请注明文章来自SAP师太技术博客( 博/客/园www.cnblogs.com):www.cnblogs.com/jiangzhengjun,并以超链接形式标明文章原始出处,否则将 ...
- JS学习笔记(三) 对象
参考资料: 1. http://www.w3school.com.cn/js/js_objects.asp ☂ 知识点: ☞ Javascript中的所有事物都是对象. ☞ Javascript是基于 ...
- NYOJ 93 汉诺塔(三)
汉诺塔(三) 时间限制:3000 ms | 内存限制:65535 KB 难度:3 描述 在印度,有这么一个古老的传说:在世界中心贝拿勒斯(在印度北部)的圣庙里,一块黄铜板上插着三根宝石针.印度 ...
- css 常用样式命名规则
大家在写css的时候,对一些html标签起一个合适的名字是个很头疼的事情,现在给大家分享项目中常用的名字供参考. 外套:wrap ——用于最外层 头部:header ——用于头部 主要内容:mai ...