• UTF-7编码


    1 编码    1

    2 编码代码(C++    2

    3 解码代码(C++    4

    4 测试代码(VC++    7

    1 编码

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

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

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

    3UTF-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; //是否正在编码

    //编码的第几个字符 123123……

    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 += ''; //末尾添加一个

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

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

  • 相关阅读:
    2018年9月28日CCPC秦皇岛站参赛总结
    数学:二次剩余与n次剩余
    数学:拓展Lucas定理
    BZOJ2301:莫比乌斯反演+二维容斥解决GCD范围计数
    数学:莫比乌斯反演-约数个数和
    数学:莫比乌斯反演-GCD计数
    关于cnblogs至github上blog的搬迁
    友链——一群dalao
    折半搜索(meet in the middle)
    关于爆搜
  • 原文地址:https://www.cnblogs.com/hanford/p/6106322.html
Copyright © 2020-2023  润新知