Symbian OS上的檔案操作和UNICODE轉換
最近研究了一下在Symbian作業系統上的檔案操作,做一下整理,以做回顧交流。
實現的功能如下:將一個class裡面的成員變數TBuf16 m_iSevrName 和 TInt m_iPort,通過一個檔案Server.txt儲存和讀取操作。因為Symbian中的TBuf16必須讀取unicode字元,故有兩種方法實現,一是將檔案儲存為UNICODE檔案然後讀取,另外一種就是讀取ANSI檔案到buffer,由程式實現將buffer轉為UNICODE字元。
1.寫檔案儲存變數
TBuf(TBufC)是Symbian系統中表示字元的一種方式,緩衝描述符,包含資料本身和資料的長度,注意此長度是unicode字元的長度,即是以short為單位的。可以通過TBuf的Ptr()成員函式得到該變數字元的地址指標,然後再逐一操作。
FILE* fp=fopen("c://Server.txt","w");
if(fp)
{
char chBufServ[20];
char chBufPort[8];
m_iSevrName.Trim();
int i = 0;
for(i=0; i chBufServ[i] = *(m_iSevrName.Ptr()+i);
chBufServ[i] = '/r';
chBufServ[i+1] = '/n';
sprintf(chBufPort,"%d/r/n",m_iPort);
fwrite(chBufServ,strlen(chBufServ),1,fp);
fwrite(chBufPort,strlen(chBufPort),1,fp);
fclose(fp);
}
2.從檔案讀取字元並給變數賦值
檔案的儲存很簡單,主要是在檔案讀取賦值時把我搞的昏頭轉向^_^。
先說一下怎麼區分unicode檔案和ANSI檔案:所有Unicode編碼的文字檔案,其檔案頭2個位元組一定是"0xff","0xfe",只要先讀出這兩個位元組,就可以判斷是不是Unicode編碼的檔案了。
char cFirst[2];
fread(iFileHandle, cFirst, 2);
if( psFirst[0] == '/xff' && psFirst[1] == '/xfe' )用這條語句就可以判斷了。
首先以第一種方式實現,直接讀取UNICODE檔案賦值:
1).
FILE* fp=fopen("c://Server.txt","rb"); //Server.txt是UNICODE格式檔案
if(fp) {
fseek(fp,0,2);//2即SEEK_SET表示Beginning of file
int nLen=ftell(fp);
if(nLen<1)
{
fclose(fp);
return;
}
fseek(fp,2,0); //注意此處跳過2位元組,即表示UNICODE檔案的符號"0xff","0xfe"
nLen-=2;
wchar_t *wstr=new wchar_t[nLen+1];
fread(wstr, nLen, 1, fp);
wstr[nLen]=0; //加入結束符
fclose(fp);
short * psip=(short*)wstr;
short* token = GetLine(psip);
int i = 0;
while( token != NULL )
{
switch(i)
{
case 0:
{
m_iSevrName.Append((TUint16*)token,wcslen((wchar_t*)token));
}
break;
case 1:
{
int nLen = wcslen((wchar_t*)token);
char pTmpBuf[5];
int i = 0;
for(i=0; i pTmpBuf[i] = *(token+i);
pTmpBuf[i] = 0; //加入結束符
m_iPort = atoi(pTmpBuf);
}
break;
}
/* Get next token: */
token = GetLine(psip);
i++;
}
}
注意case 0的情況,如果token是short* 型別,則m_iSevrName呼叫Append後,其length()返回的是UNICODE的字元個數,而如果是wchar_t*型別的wstr ,則iSevrName的length()函式返回的是ANSi字元的個數,必須呼叫用SetLength()設定,即:m_iSevrName.Append((TUint16*) wstr,wcslen(wstr));
m_iSevrName.SetLength(m_iSevrName.Length()/2);
(在這個問題上浪費了我不少時間)。
其中上面讀取一行字元的函式GetLine實現如下:
short* GetLine(LPSHORT& pBuf)
{
short* pRet=pBuf;
while(*pBuf && *pBuf!='/r' && *pBuf!='/n') pBuf++;
*pBuf=0;
pBuf++;
while(*pBuf &&(*pBuf=='/r' || *pBuf=='/n')) pBuf++;
if(pRet==pBuf||*pRet==0)
return NULL;
return pRet;
}
2)以上是直接讀取UNICODE檔案實現,下面說一下第二種方法,即讀取ANSI檔案到快取,然後轉換為UNICODE字元。Windows系統中比較簡單,呼叫其API函式WideCharToMultiByte、MultiByteToWideChar可以在兩種字元間互相轉換,而在Symbian系統中就沒有那麼簡單了:
FILE* fp=fopen("c://Server.txt","rb");
if(fp) {
fseek(fp,0,2);
int nLen=ftell(fp);
if(nLen<1)
{
fclose(fp);
return;
}
unsigned char* pBuf1=new unsigned char[nLen+1];
fseek(fp,0,0);
fread(pBuf1,nLen,1,fp);
pBuf1[nLen]=0; //結束符
fclose(fp);
fp=NULL;
//convert to unicode
TPtrC8 aForeign;
aForeign.Set(pBuf1,nLen);
CCnvCharacterSetConverter* pcc= CCnvCharacterSetConverter::NewLC();
if (pcc->PrepareToConvertToOrFromL(KCharacterSetIdentifierGbk, iEikonEnv->FsSession()) != CCnvCharacterSetConverter::EAvailable)
{
CleanupStack::PopAndDestroy();
delete pBuf1;
return;
}
HBufC* iInfoText = HBufC::NewL(aForeign.Length());
TPtr16 ptr = iInfoText->Des();
TInt aState=CCnvCharacterSetConverter::KStateDefault;
pcc->ConvertToUnicode(ptr, aForeign, aState);
CleanupStack::PopAndDestroy();
nLen*=2;
short* pBuf=(short*)ptr.Ptr();
short * psip=pBuf;
short* token = GetLine(psip);
int i = 0;
while( token != NULL )
{ ...... //下面實現同第一種方法
注意此轉換方法在Symbian的模擬器上不能執行和除錯,只能在real device上執行,不能除錯對我們程式設計師來說比較難受,如果你選擇了這種方法,那麼就祈禱上帝讓它能夠正確執行吧^_^。
TBuf m_iSevrName;
void SetDefaultChnl(const TDesC& aServName, TInt nRoom)
{
// m_iServName = aServName; //這種寫法是錯誤的
m_iSevrName.Delete(0,m_iSevrName.Length()); //必須先清除原來的內容
m_iSevrName.Append(aServName);
m_iRoom = nRoom;
}
利用TDesC為TBuf變數賦值時,必須首先呼叫TBuf的Delete()函式清空內容,否則如果用第一種方法,該TBuf變數不會正確賦值,儘管除錯時跟蹤TBuf變數的Length和iBuf指標內容都顯示是正確的。
當我剛開始學習Symbian時,我遇到的第一件事情就是Symbian OS字串的處理和使用問題。要學習Symbian字串的使用,必須費一定腦筋才行。但是一旦你掌握了其中的要領,它就變得容易多了。
注意,理解本文的前提是對Symbian作業系統的工作機理有一定了解。
2. 背景
你要做的第一件事情是記住字串描述符層次結構圖。這是很重要的,因為以後所有你要使用的五個描述符都派生於某些類,你必須瞭解它們分別是從哪些類派生的,以便確定應該使用哪些特別描述符及其使用場所。本文中我不準備解釋什麼是緩衝描述符及堆描述符的含義,以及可修改的描述符和不可修改的描述符是什麼含義。但是,我相信你必須對上面的術語有足夠的瞭解才行。Symbian描述符層次結構看起來相當絕妙。你可以參考下圖,該圖來源於newlc。
3. TPtrC用法
其字面含義是"一個指向不可被操作的資料的指標"。關於TPtrC,首先要記住,它不包含對自己的一些操作函式,而只含有構造器和設定方法。另外,既然它派生於TDesC,它就包含了TDesC的所有功能。
指標指向資料的方式有下面兩種:
·先建立一個空的TPtrC,然後用Set(...)函式把它指向一些資料。
·通過使用任何一個過載的建構函式,在構造過程中傳遞資料。
讓我們通過下面幾個例子來看一下上面的描述:
例項1:-從TBuf和TbufC中取得TPtrC:
LIT(KText , "Test Code"); TBufC<10> Buf ( KText ); OR(/) TBuf<10> Buf ( KText ); // 使用構造器建立TPtr TPtrC Ptr (Buf); //使用成員函式建立TPtr TPtrC Ptr1; Ptr1.Set(Buf); |
例項2:-從TText*中取得TPtrC:
下面的例項使用了TText16:
TText * text = _S("Hello World/n"); TPtrC ptr(text); // 或 TPtrC Ptr1; Ptr1.Set(text); //要只儲存Ttext的一部分,我們可以使用下面的語句 //這個描述符指標將只儲存Hello TPtrC ptr4(text,5); |
例項3:-從另外一個TPtrC取得TPtrC:
你可以容易地把一個TPtrC賦值給另一個TPtrC。
TText * text = _S("Hello World/n"); TPtrC ptr(text); //從另外一個TPtrC取得TPtrC TPtrC p1(ptr); //或 TPtrC p2; p2.Set(ptr); |
例項4:-從TPtrC中取得TText *:
我們可以通過Ptr()成員使用來從TPtrC中取得TText *。
//設定TPtrC _LIT(KText,"Test Code"); TBufC<10> Buf ( KText ); TPtrC Ptr1 (Buf); //取得TText* TText* Text1 = (TText *)Ptr1.Ptr(); |
4. TBufC的用法
上面關於TPtrC的使用舉例,有助於理解TBufC的用法,不過下面有幾個例子是關於如何建立TBufC。
例項5:-例項化TBufC:
//用文字例項化 _LIT(Ktext, "TestText"); TBufC<10> Buf (Ktext); //或 TBufC<10> Buf2; Buf2 = Ktext; //用現有的TBufC來建立一個新的TBufC TBufC<10> Buf3(Buf2); |
TBufC一般用於文字資料。對於二進位制資料,應顯示地使用TBufC8。儘管TBufC意味著資料不能被修改(’C’代表Constant:不變的),但是還有兩種方法可以改變資料:
·資料可以使用賦值運算子進行替換。
·通過使用Des()函式來為緩衝區資料構建一個TPtr可修改的指標描述符。
讓我們看改變TBufC的上下文的第一步。
例項6:-改變TBufC的上下文:
//測試用的一些文字 _LIT(Ktext , "Test Text"); _LIT(Ktext1 , "Test1Text"); //生成TPtrC TBufC<10> Buf1 ( Ktext ); TBufC<10> Buf2 ( Ktext1 ); //改變Buf2的上下文 Buf2 = Buf1; //建立一個空的TbufC並把它賦給Buf1 TBufC<10> Buf3; Buf3 = Buf1; |
另一種改變TBufC的上下文內容的方式是使用Des()成員函式。這個成員函式使用TPtr成員返回一個TPtr可修改的指標描述符。TPtr的最大長度是TBufC模板引數的值。所有的操作函式都來源於基類TdesC。
例項7:-使用Des()來改變TBufC的上下文:
_LIT(Ktext , "Test Text"); _LIT(KXtraText , "New:"); TBufC<10> Buf1 ( Ktext ); TPtr Pointer = Buf1.Des(); // 刪除最後4個字元 Pointer.Delete(Pointer.Length()-4, 4 ); //現在作相應的長度改變 TInt Len = Pointer.Length(); // 新增一個新串 Pointer.Append(KXtraText); Len = Pointer.Length(); //要完全改變上面的緩衝區,我們可以使用下面的語句: _LIT(NewText , "New1"); _LIT(NewText1 , "New2"); TBufC<10> Buf2(NewText); //改變上下文 Pointer.Copy(Buf2); //或者直接進行字面複製 Pointer.Copy(NewText1); //所有上面所做的變化實際上改變了Buf1的上下文 |
5. 使用堆描述符HBufC
當我們不知道描述符中資料的大小時,HBufC是可選用的描述符。這裡的’C’代表不變的(constant),這意味著資料是不可改變的,但是它在兩種情況下也可以改變,就象對於TBufC的情況所做的改變一樣。第一種情況是使用賦值運算子,第二種情況是使用可修改的指標描述符,如使用成員函式時的TPtr。在使用HbufC時,要記住兩種情況:
·如果你需要把HbufC傳遞給一個用TDesC&作為引數的函式,你只須簡單地取消對HBufC指標的參照即可。
·可以通過使用ReAlloc函式來改變堆描述符緩衝區的大小,就象對於TBufC的情況一樣.
例項8:-HbufC的用法:
//建立一個堆描述符,有兩種方法 //第一種方法使用New(),NewL()或NewLC()之一 //讓我們看一個例子.這裡將構建一個HbufC:所用資料空間為15,但是當前大小是0 HBufC * Buf = HBufC::NewL(15); // 第二種方法使用 // 現有描述符的Alloc(), AllocL(), 或AllocLC()方法。這個新的堆描述符用描述符的內容自動初始化 _LIT (KText , "Test Text"); TBufC<10> CBuf = KText; HBufC * Buf1 = CBuf.AllocL(); // 我們檢查一下大小和長度。這裡大小是18,而長度是9 TInt BufSize = Buf->Size(); TInt BufLength = Buf->Length(); // 改變HbufC的指向 _LIT ( KText1 , "Text1"); //使用賦值運算子來改變指向KText1的緩衝區 *Buf1 = KText1; // 下面通過可修改的指標描述符來改變 資料 TPtr Pointer = Buf1->Des(); Pointer.Delete( Pointer.Length() - 2, 2 ); // 所有能對 TBufC 進行的操作在些都可用 //下面是一個這樣的操作 _LIT ( KNew, "New:"); Pointer.Append( KNew ); |
6. TPtr的用法
我們使用它來取代TBufC和HBufC,因為我最瞭解它。因此,讓我們先記住如何建立TPtr。
·用另一個TPtr。
·從TBufC,或者通過成員函式Des()使用HbufC來建立。
·從一個指向記憶體的外部指標並指定最大長度。
·從一個指向記憶體的外部指標並指定資料及其最大長度。
例項9:-TPtr的用法:
//先讓我們看一下兩種取得TPtr的方法 _LIT(KText, "Test Data"); TBufC<10> NBuf ( KText ); TPtr Pointer = NBuf.Des(); //第一種方法 TPtr Pointer2 ( Pointer ); //第二種方法使用一個記憶體區段,用於儲存資料和最大長度 TText * Text = _S("Test Second"); TPtr Pointer3 ( Text ,11, 12); // 現在我們看一下,怎麼用TPtr 替換資料,這完全可以通過 //賦值運算子或拷貝函式來實現 _LIT(K1, "Text1"); _LIT(K2, "Text2"); Pointer2 = K1; // 資料是Text1 Pointer.Copy(K2); // 資料是Text2; // 我們還可以改變資料的長度或把它設定為0 Pointer2.SetLength(2); // 只剩下 Te兩個字元 Pointer2.Zero(); // 把長度設定為0 //可以使用delete 函式來更改資料,如前面的例中所示 |
7. TBuf的用法
在這個資料結構中,其中的資料並不是固定不變的。運算、例項化和賦值都與TBufC一致;對於它的修改操作,與TPtr一致,象複製、刪除、賦值等等。我想這一部分就不用再給出例子了。
Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=819709
相關文章
- Symbian中ini檔案的使用
- Symbian中操作ini檔案
- ofd檔案如何轉換成pdf格式 電腦上ofd檔案如何轉換成pdf格式
- ASM 檔案與本地檔案的轉換ASM
- 從 unicode 到位元組的轉換Unicode
- Programming Java 2 Micro Edition for Symbian OSJava
- PDF檔案轉換為DWF檔案
- WOR檔案轉換成GST檔案
- caj檔案怎麼轉換成word文件,簡單的檔案格式轉換教程
- Torrent檔案的解析與轉換
- tkprof 轉換trc檔案
- 處理檔案上傳時的訊息格式轉換問題
- 將Schema檔案轉換為Java檔案Java
- 把 .xyz 檔案轉換成 .ply 檔案
- 用Aspose-Java免費實現 PDF、Word、Excel、Word互相轉換並將轉換過得檔案上傳OSS,返回轉換後的檔案路徑JavaExcel
- JAVA類檔案操作和異常Java
- aspose word轉換pdf檔案後將pdf檔案轉換為圖片png
- 如何將.ipynb檔案轉換為.py檔案
- heic檔案如何轉換jpg?
- plist檔案格式轉換器
- Linux轉換檔案格式Linux
- OS認證以及口令檔案的一點總結(轉)
- Symbian 資原始檔解析
- php的漢字轉換: Unicode(UTF8)->GBK (轉)PHPUnicode
- WindowsCE下Unicode和Ansi字元間互相轉換的例子 (轉)WindowsUnicode字元
- 【ASM】ASM資料檔案和OS檔案(FILESYSTEM)轉移方法總結ASM
- gvim 與 開啟·unicode 檔案Unicode
- python實現中文和unicode轉換PythonUnicode
- Mxnet模型檔案轉換為Pb模型檔案模型
- 檢測檔案編碼,轉換檔案編碼
- 轉換RDBA的檔案和資料塊地址(轉)
- PDF檔案如何轉換為能編輯的CAD檔案
- 【原創】ASM下的資料檔案轉換為普通檔案ASM
- perl檔案上傳程式,支援多檔案! (轉)
- 使用 Fstransform 轉換檔案系統ORM
- java 字串與檔案相互轉換Java字串
- 使用sratoolkit轉換SRA檔案格式
- RTF 批量轉換為 DOCX 檔案