Symbian OS上的文件操作和UNICODE转换
<div style="display: block;" class="diaryContent"> 本文整理总结了一下在Symbian系统上进行文件操作的一些体会,实现了通过文件保存、读取TBuf和TInt变量的功能,其中涉及到UNICODE和ANSI之间字符的转换。最近研究了一下在Symbian操作系统上的文件操作,做一下整理,以做回顾交流。
实现的功能如下:将一个class里面的成员变量TBuf16<KMaxServerNameLen> m_iSevrName 和 TIntm_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;
char chBufPort;
m_iSevrName.Trim();
int i = 0;
for(i=0; i<m_iSevrName.Length(); i++)
chBufServ = *(m_iSevrName.Ptr()+i);
chBufServ = '\r';
chBufServ = '\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;
fread(iFileHandle, cFirst, 2);
if( psFirst == '\xff' && psFirst == '\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;
fread(wstr, nLen, 1, fp);
wstr=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;
int i = 0;
for(i=0; i<wcslen((wchar_t*)token); i++)
pTmpBuf = *(token+i);
pTmpBuf = 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;
fseek(fp,0,0);
fread(pBuf1,nLen,1,fp);
pBuf1=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上运行,不能调试对我们程序员来说比较难受,如果你选择了这种方法,那么就祈祷上帝让它能够正确运行吧^_^。
页:
[1]