描述符<下>轉(zhuǎn)換
業(yè)余有時(shí)候把一個(gè)事情當(dāng)作任務(wù)來(lái)做的時(shí)候,往往會(huì)很受限制,就象這篇文檔,上次寫了個(gè)上篇,關(guān)于描述符的下篇,自己就遲遲沒有勇氣和時(shí)間寫完,好幾次都想靜下心來(lái)好好完成它,但是都未能如愿,可如果不寫顯然我也不好意思寫其它的一些東西,閑話提到這里,花了幾天業(yè)余時(shí)間總算是完成了,該文質(zhì)量不足之處還望讀者您見諒。
通過前面關(guān)于描述符概念和使用的簡(jiǎn)單描述,下面我們直接進(jìn)入描述符轉(zhuǎn)換的主題。
雖然描述符有五類,但是作為描述符變量用的,只有三類即棧描述符、堆描述符、指針描述符。所以本文所述描述符的轉(zhuǎn)換也只是在這三種類型間展開,這三類描述符之間的互相轉(zhuǎn)換其實(shí)可以用下面這種偽代碼方式給出:
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());
由上面可知指針型可以起堆型和棧型描述符的中間過渡的橋梁作用。
不可修改向可修改描述符的轉(zhuǎn)換
原則1:通過不可修改描述符類內(nèi)的Des()函數(shù),將不可修改的描述符轉(zhuǎn)換成可修改的指針描述符
示例1:TBufC轉(zhuǎn)換成TPtr
_LIT(KText, "Test Data");
TBufC<10> NBuf ( KText );
TPtr Pointer = NBuf.Des();
示例2:HBufC轉(zhuǎn)換成TPtr
HBufC * Buf = HBufC::NewL(15);
_LIT (KText , "Test Text");
*Buf = KText;
TPtr Pointer = Buf->Des();
原則2:通過TPtr的構(gòu)造函數(shù)或Set()函數(shù)可以將TPtrC描述轉(zhuǎn)換為可修改的指針描述符
示例3:TPtrC到TPtr
const TText * text1 = _S("Hello World\n");
TPtrC Ptr1(text1);
TPtrC Ptr2(Ptr1);
//可以通過構(gòu)造函數(shù)
TPtr Ptr3((TUint16 *)(Ptr1.Ptr()), Ptr1.Length());
//也可以通過Set()函數(shù)
Ptr3.Set((TUint16 *)(Ptr1.Ptr()),Ptr1.Length(), Ptr1.Length());
8位和16位之間的描述符轉(zhuǎn)換
8位到16位的描述符轉(zhuǎn)換
原則1:通過將兩個(gè)8位描述符的內(nèi)容合并為一個(gè)16位描述符的方法實(shí)現(xiàn)內(nèi)存不動(dòng),內(nèi)存塊類型強(qiáng)轉(zhuǎn)(我稱其為保留描述符字節(jié)大小方法)。
示例4:8bit To 16bit保留描述符字節(jié)大小方法1
_LIT8(KText , "Test Text");
TBuf8<20> iBuf8(KText);//描述符實(shí)際占用了9個(gè)字節(jié)9個(gè)8位描述符
TBuf<20> iBuf16;
//實(shí)現(xiàn)內(nèi)存塊的強(qiáng)轉(zhuǎn)
TPtrC16 ptr16(reinterpret_cast<const TUint16*>(iBuf8.Ptr()), (iBuf8.Length()/2));
//真實(shí)的內(nèi)存不動(dòng)已經(jīng)結(jié)束,這里是重新申請(qǐng)了一塊內(nèi)存并實(shí)現(xiàn)內(nèi)存賦值拷貝
iBuf16 = ptr16;//描述符實(shí)際占用了8個(gè)字節(jié)4個(gè)16位描述符,導(dǎo)致數(shù)據(jù)丟失
由上面的這個(gè)例子明顯是丟失了數(shù)據(jù)了,原因就出在設(shè)置長(zhǎng)度時(shí)用了(iBuf8.Length()/2),為了剔除錯(cuò)誤,我后來(lái)改了一個(gè)新的示例6
示例6:8bit To 16bit保留描述符字節(jié)大小方法2(由于上例用了TPtrC,所以該例使用TPtr指針,以擴(kuò)展應(yīng)用)
_LIT8(KText , "Test Text");
TBuf8<20> iBuf8;
iBuf8.FillZ(20);
iBuf8 = KText;//實(shí)際占用9字節(jié)9描述符
TBuf<20> iBuf16;
TPtr ptr16(reinterpret_cast<TUint16*>(const_cast<TUint8*>(iBuf8.Ptr())),
((iBuf8.Length()+1)/2),((iBuf8.Length()+1)/2));
iBuf16 = ptr16;//實(shí)際占用10字節(jié)5描述符,但是第10個(gè)字節(jié)為0零值,也即9字節(jié)大小有用
注:其實(shí)這里用堆描述符來(lái)說(shuō)明可能更好些,但是本人在調(diào)試過程中為了能夠看到調(diào)試的效果,所以用了TBuf;而且個(gè)人覺得通常這種方法主要在文件讀取等實(shí)際過程中用到,如果要轉(zhuǎn)換為16位的話,肯定是偶數(shù)大小的8位描述符。
原則2:重新構(gòu)建內(nèi)存塊使用描述符的copy函數(shù)將8位字符的高字節(jié)置為0低字節(jié)不變,進(jìn)行拷貝轉(zhuǎn)換(我稱其為保留描述符長(zhǎng)度方法)。
示例7
_LIT8(KText , "Test Text");
TBuf8<20> iBuf8(KText);//實(shí)際占用了9個(gè)描述符9個(gè)字節(jié)
TBuf<20> iBuf16;
iBuf16.Copy(iBuf8);//實(shí)際占用了9個(gè)描述符18個(gè)字節(jié)
原則3:使用charconv.lib內(nèi)的API函數(shù)將8位的UTF8描述符轉(zhuǎn)換為16位的Unicode 描述符
CnvUtfConverter::ConvertToUnicodeFromUtf8(iBuf, iBuf8);
注:在使用這種方法時(shí)除了包含charconv.lib庫(kù),還應(yīng)該包含utf.h頭文件
原則4:使用GBK轉(zhuǎn)Unicode的方法
注:原則3和4是我在實(shí)際中常用的方法,涉及到各種編碼的問題,暫時(shí)不做大的展開,下次使用中文的整理時(shí)再展開。
16位到8位的描述符轉(zhuǎn)換
原則1:通過將一個(gè)16位描述符拆分為兩個(gè)8位描述符的方法實(shí)現(xiàn)內(nèi)存不動(dòng),內(nèi)存塊類型強(qiáng)轉(zhuǎn)(我稱其為保留描述符字節(jié)大小方法)
示例8
_LIT(KText , "Test 文本");
TBuf<20> iBuf(KText);//描述符實(shí)際占用了14個(gè)字節(jié)7個(gè)16位描述符 //實(shí)現(xiàn)內(nèi)存塊的強(qiáng)轉(zhuǎn)
TPtrC8 ptr8(reinterpret_cast<const TUint8*>(iBuf.Ptr()), (iBuf.Size()));
//真實(shí)的內(nèi)存不動(dòng)已經(jīng)結(jié)束,這里是重新申請(qǐng)了一塊內(nèi)存并實(shí)現(xiàn)內(nèi)存賦值拷貝
TBuf8<20> iBuf8;
iBuf8 = ptr8;//描述符實(shí)際占用了14個(gè)字節(jié)14個(gè)8位描述符
以上
原則2:重新構(gòu)建內(nèi)存塊使用描述符的copy函數(shù)將16位描述符的,進(jìn)行拷貝轉(zhuǎn)換(我稱其為保留描述符長(zhǎng)度方法)。
示例9:
_LIT(KText , "Test 文本");
TBuf<20> iBuf(KText);// 描述符實(shí)際占用了14個(gè)字節(jié)7個(gè)16位描述符
TBuf8<20> iBuf8;
iBuf8.Copy(iBuf);//描述符實(shí)際占用了7個(gè)字節(jié)7個(gè)描述符,非ASCII字符值轉(zhuǎn)為1
注:該種方法在純ASCII碼的轉(zhuǎn)換時(shí)可行,其它數(shù)據(jù)大于255的時(shí)候就會(huì)丟失數(shù)據(jù)。
原則3:使用charconv.lib內(nèi)的API函數(shù)將16位的Unicode描述符轉(zhuǎn)換為8位的UTF8描述符。
CnvUtfConverter::ConvertFromUnicodeToUtf8(iBuf8, iBuf);
原則4:使用Unicode轉(zhuǎn)GBK的方法
同前面理,以后我會(huì)再講到。
由于最近做通信模塊時(shí)組解包用的比較多,為此經(jīng)常會(huì)將memcpy,strcpy,sprintf,sscanf等函數(shù)在char字符串和描述符串內(nèi)存塊之間的直接使用,個(gè)人覺得描述符一旦取得了后面數(shù)據(jù)區(qū)的首指針,那么內(nèi)存塊的這些操作沒有什么好展開,直接用函數(shù)大家都會(huì),當(dāng)然本人也推薦讀者使用文后的char字符串和Symbian描述符串的轉(zhuǎn)換方法。
在整理過程種,也有其它類型與描述符的轉(zhuǎn)換,我就摘錄在本文后面作為mark和備查:
1. TTime轉(zhuǎn)TBuf型
TBuf<32> theTime;//存儲(chǔ)轉(zhuǎn)換后的時(shí)間
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轉(zhuǎn)TBuf型
TTime currentTime;//聲明一個(gè)TTime類型
currentTime.HomeTime();//設(shè)置TTime為當(dāng)前時(shí)間
TDateTime tdt=currentTime.DateTime();//TTime ---> TdateTime
TBuf<32> tmp;//存儲(chǔ)轉(zhuǎn)換完的Buf
tmp.AppendNum(tdt.Year());//用AppendNum()方法將一個(gè)Tint加入到TBuf中。
_LIT(gang,"-");//聲明一個(gè)橫線分隔年月日,同樣可聲明冒號(hào)分隔小時(shí)分秒
tmp.Append(gang);
tmp.AppendNum(tdt.Month());
tmp.Append(gang);
tmp.AppendNum(tdt.Day());//…………時(shí)分秒的轉(zhuǎn)換同上
3. TBuf和Tint互轉(zhuǎn)型
// 15位數(shù)字
TInt iNum1(123456789009876);
// TInt轉(zhuǎn)TBuf
iBuf.Num(iNum1);//當(dāng)buf只用來(lái)轉(zhuǎn)Tint時(shí)可以使用AppendNum,但是性質(zhì)是不一樣的
// 使用iBuf包含的內(nèi)容創(chuàng)建TLex對(duì)象
TLex iLex(iBuf);
TInt iNum2;
//TBuf轉(zhuǎn)TInt
iLex.Val(iNum2);// Num2現(xiàn)在包含了15位數(shù)字
4. TBuf轉(zhuǎn)TDateTime型
將長(zhǎng)的TBuf截成小段,分別是年月日時(shí)分秒,通過下面TBuf轉(zhuǎn)TInt ,再分別把轉(zhuǎn)換成TInt的年月日取出,通過TDateTime的setYear(),setMonth()等方法將時(shí)間set進(jìn)TdateTime。
5. .將symbian串轉(zhuǎn)換成char串
char* p = NULL;
TBuf8<20> buf( _L( "aaaaa" ) );
p = (char *)buf.Ptr();
6.將char串轉(zhuǎn)換成symbian串
char* cc = "aaaa";
TPtrC8 a;
a.Set( (const TUint8*)cc , strlen(cc) );
本文參考了一些論壇資料,至于資料索引,我也無(wú)法給出,望讀者見諒,有錯(cuò)誤之處還望指出。
posted on 2007-11-28 22:51
frank.sunny 閱讀(4960)
評(píng)論(15) 編輯 收藏 引用 所屬分類:
symbian 開發(fā)