zoukankan      html  css  js  c++  java
  • 描述符转换

    在练习文件的读写时,不知该怎么转换  8 位到 16位了,上网搜出了下面这篇文章

    原文地址:http://www.cppblog.com/franksunny/archive/2007/11/28/37469.html

    -----------------------------------

    业余有时候把一个事情当作任务来做的时候,往往会很受限制,就象这篇文档,上次写了个上篇,关于描述符的下篇,自己就迟迟没有勇气和时间写完,好几次都想静下心来好好完成它,但是都未能如愿,可如果不写显然我也不好意思写其它的一些东西,闲话提到这里,花了几天业余时间总算是完成了,该文质量不足之处还望读者您见谅。

     

    通过前面关于描述符概念和使用的简单描述,下面我们直接进入描述符转换的主题。

    虽然描述符有五类,但是作为描述符变量用的,只有三类即栈描述符、堆描述符、指针描述符。所以本文所述描述符的转换也只是在这三种类型间展开,这三类描述符之间的互相转换其实可以用下面这种伪代码方式给出:

    TBuf<20> iBuf;

    TPtr iPtr((const_cast<TUint16*>(iBuf.Ptr())),iBuf.Length(), iBuf.Length());

    HBufC     *iHbuf;

    iBuf = iPtr;

    iBuf = iHbuf->Des();

    iPtr.Set((const_cast<TUint16*>(iBuf.Ptr())),iBuf.Length(), iBuf.Length());

    由上面可知指针型可以起堆型和栈型描述符的中间过渡的桥梁作用。

     

    不可修改向可修改描述符的转换

    原则 1 :通过不可修改描述符类内的 Des() 函数,将不可修改的描述符转换成可修改的指针描述符

    示例 1 TBufC 转换成 TPtr

           _LIT(KText, "Test Data");

           TBufC<10> NBuf ( KText );

           TPtr     Pointer = NBuf.Des();

    示例 2 HBufC 转换成 TPtr

    HBufC * Buf = HBufC::NewL(15);

           _LIT (KText , "Test Text");

           *Buf = KText;

           TPtr Pointer = Buf->Des();

     

    原则 2 :通过 TPtr 的构造函数或 Set() 函数可以将 TPtrC 描述转换为可修改的指针描述符

    示例 3 TPtrC TPtr

    const TText * text1 = _S("Hello World\n");

    TPtrC Ptr1(text1);

    TPtrC Ptr2(Ptr1);

    // 可以通过构造函数

    TPtr Ptr3((TUint16 *)(Ptr1.Ptr()), Ptr1.Length());

    // 也可以通过 Set() 函数

    Ptr3.Set((TUint16 *)(Ptr1.Ptr()),Ptr1.Length(), Ptr1.Length());

     

    8 位和 16 位之间的描述符转换

    8 位到 16 位的描述符转换

    原则 1 :通过将两个 8 位描述符的内容合并为一个 16 位描述符的方法实现内存不动,内存块类型强转(我称其为保留描述符字节大小方法)。

    示例 4 8bit To 16bit 保留描述符字节大小方法 1

    _LIT8(KText , "Test Text");

    TBuf8<20> iBuf8(KText);// 描述符实际占用了 9 个字节 9 8 位描述符

    TBuf<20> iBuf16;

    // 实现内存块的强转

    TPtrC16 ptr16(reinterpret_cast<const TUint16*>(iBuf8.Ptr()), (iBuf8.Length()/2));

    // 真实的内存不动已经结束,这里是重新申请了一块内存并实现内存赋值拷贝

    iBuf16 = ptr16;// 描述符实际占用了 8 个字节 4 16 位描述符,导致数据丢失

    由上面的这个例子明显是丢失了数据了,原因就出在设置长度时用了 (iBuf8.Length()/2) ,为了剔除错误,我后来改了一个新的示例 6

    示例 6 8bit To 16bit 保留描述符字节大小方法 2 (由于上例用了 TPtrC ,所以该例使用 TPtr 指针,以扩展应用)

    _LIT8(KText , "Test Text");

    TBuf8<20> iBuf8;

    iBuf8.FillZ(20);

    iBuf8 = KText;// 实际占用 9 字节 9 描述符

    TBuf<20> iBuf16;

    TPtr ptr16(reinterpret_cast<TUint16*>(const_cast<TUint8*>(iBuf8.Ptr())),
       ((iBuf8.Length()+1)/2),((iBuf8.Length()+1)/2));

    iBuf16 = ptr16;// 实际占用 10 字节 5 描述符,但是第 10 个字节为 0 零值,也即 9 字节大小有用

    注:其实这里用堆描述符来说明可能更好些,但是本人在调试过程中为了能够看到调试的效果,所以用了 TBuf ;而且个人觉得通常这种方法主要在文件读取等实际过程中用到,如果要转换为 16 位的话,肯定是偶数大小的 8 位描述符。

     

    原则 2 :重新构建内存块使用描述符的 copy 函数将 8 位字符的高字节置为 0 低字节不变,进行拷贝转换(我称其为保留描述符长度方法)。

    示例 7

    _LIT8(KText , "Test Text");

    TBuf8<20> iBuf8(KText);// 实际占用了 9 个描述符 9 个字节

    TBuf<20> iBuf16;

    iBuf16.Copy(iBuf8);// 实际占用了 9 个描述符 18 个字节

     

    原则 3 :使用 charconv.lib 内的 API 函数 8 位的 UTF8 描述符转换为 16 位的 Unicode 描述符

    CnvUtfConverter::ConvertToUnicodeFromUtf8(iBuf, iBuf8);

    注:在使用这种方法时除了包含 charconv.lib 库,还应该包含 utf.h 头文件

     

    原则 4 :使用 GBK Unicode 的方法

    注:原则 3 4 是我在实际中常用的方法,涉及到各种编码的问题,暂时不做大的展开,下次使用中文的整理时再展开。

     

    16 位到 8 位的描述符转换

    原则 1 :通过将一个 16 位描述符拆分为两个 8 位描述符的方法实现内存不动,内存块类型强转(我称其为保留描述符字节大小方法)

    示例 8

    _LIT(KText , "Test 文本 ");

    TBuf<20> iBuf(KText);// 描述符实际占用了 14 个字节 7 16 位描述符                             // 实现内存块的强转

    TPtrC8 ptr8(reinterpret_cast<const TUint8*>(iBuf.Ptr()), (iBuf.Size()));

    // 真实的内存不动已经结束,这里是重新申请了一块内存并实现内存赋值拷贝

    TBuf8<20> iBuf8;

    iBuf8 = ptr8;// 描述符实际占用了 14 个字节 14 8 位描述符

    以上

    原则 2 :重新构建内存块使用描述符的 copy 函数将 16 位描述符的,进行拷贝转换(我称其为保留描述符长度方法)。

    示例 9

    _LIT(KText , "Test 文本 ");

    TBuf<20> iBuf(KText);// 描述符实际占用了 14 个字节 7 16 位描述符

    TBuf8<20> iBuf8;

    iBuf8.Copy(iBuf);// 描述符实际占用了 7 个字节 7 个描述符,非 ASCII 字符值转为 1

    注:该种方法在纯 ASCII 码的转换时可行,其它数据大于 255 的时候就会丢失数据。

     

    原则 3 :使用 charconv.lib 内的 API 函数 16 位的 Unicode 描述符转换为 8 位的 UTF8 描述符。

    CnvUtfConverter::ConvertFromUnicodeToUtf8(iBuf8, iBuf);

     

    原则 4 :使用 Unicode GBK 的方法

    同前面理,以后我会再讲到。

     

    由于最近做通信模块时组解包用的比较多,为此经常会将 memcpy strcpy sprintf sscanf 等函数在 char 字符串和描述符串内存块之间的直接使用,个人觉得描述符一旦取得了后面数据区的首指针,那么内存块的这些操作没有什么好展开,直接用函数大家都会,当然本人也推荐读者使用文后的 char 字符串和 Symbian 描述符串的转换方法。

     

    在整理过程种,也有其它类型与描述符的转换,我就摘录在本文后面作为 mark 和备查:

    1.    TTime TBuf

    TBuf<32> theTime;// 存储转换后的时间

    TTime tt;

    tt.HomeTime();

    _LIT(KTimeFormat,"%Y%M%D%1-%2-%3 %H:%T:%S");// 格式为:2006-03-04 12:12:12

    tt.FormatL(theTime,KTimeFormat);

     

    2.    TDateTime TBuf

    TTime currentTime;// 声明一个TTime 类型

    currentTime.HomeTime();// 设置TTime 为当前时间

    TDateTime tdt=currentTime.DateTime();//TTime  --->  TdateTime

    TBuf<32> tmp;// 存储转换完的Buf

    tmp.AppendNum(tdt.Year());// AppendNum() 方法将一个Tint 加入到TBuf 中。

    _LIT(gang,"-");// 声明一个横线分隔年月日,同样可声明冒号分隔小时分秒

    tmp.Append(gang);

    tmp.AppendNum(tdt.Month());

    tmp.Append(gang);

    tmp.AppendNum(tdt.Day());//………… 时分秒的转换同上

     

    3.    TBuf Tint 互转型

    // 15 位数字

    TInt iNum1(123456789009876);

    // T Int TBuf

    iBuf.Num(iNum1);// buf 只用来转Tint 可以使用 AppendNum, 但是性质是不一样的

     

    // 使用iBuf 包含的内容创建TLex 对象

    TLex iLex(iBuf);

    TInt iNum2;

    //TBuf TInt

    iLex.Val(iNum2);// Num2 现在包含了15 位数字

     

    4.    TBuf TDateTime

    将长的 TBuf 截成小段,分别是年月日时分秒,通过下面 TBuf TInt ,再分别把转换成 TInt 的年月日取出,通过 TDateTime setYear (), setMonth ()等方法将时间 set TdateTime

     

    5.  . symbian 串转换成 char

    char* p = NULL;

    TBuf8<20> buf( _L( "aaaaa" ) );

    p = (char *)buf.Ptr();

     

    6. char 串转换成symbian

    char* cc = "aaaa";

    TPtrC8 a;

    a.Set( (const TUint8*)cc , strlen(cc) );

     

    本文参考了一些论坛资料,至于资料索引,我也无法给出,望读者见谅,有错误之处还望指出。

  • 相关阅读:
    Cookie
    JS开发常用工具函数
    手动搭建Vue之前奏:搭建webpack项目
    Redis的下载与安装
    Redis官方Tutorial
    Redis之datatype概述
    18 SQL优化
    16 SQL Mode
    17 MySQL的小技巧
    14 事务控制和锁定语句
  • 原文地址:https://www.cnblogs.com/zziss/p/1651987.html
Copyright © 2011-2022 走看看