这个小问题困了我一天一夜了,本来今天都计划写XML处理的代码了,结果又耽搁了一天。幸好后头还搞出来了。
我想写个程序,通过SOCKET获得服务器的XML文件,然后保存到本地。获取文件是搞定了,但是保存成文件时老出现乱码。
以下是会出现乱码的代码片断:
void CTecClientDlg::OnBnClickedbtnlogin()
{
// TODO: 登陆按钮,登陆后下载数据。
WORD version;
WSADATA wsaData;
int rVal=0;
version=MAKEWORD(1,1);
WSAStartup(version,(LPWSADATA)&wsaData);
SOCKET theSocket=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
if(theSocket==SOCKET_ERROR)
{
return;
}
SOCKADDR_IN serverInfo;
serverInfo.sin_family=PF_INET;
serverInfo.sin_addr.s_addr=inet_addr("192.168.0.3");
serverInfo.sin_port=htons(6603);
rVal=connect(theSocket,(LPSOCKADDR)&serverInfo,sizeof(serverInfo));
if(rVal==SOCKET_ERROR)
{
return;
}
//==========================关键是这个片段
CFile xmlFile(_T("Data.xml"),CFile::modeCreate|CFile::modeWrite);
wchar_t buf[200];
int strLast=0;
do{
memset(buf,0,200*sizeof(wchar_t));
strLast=recv(theSocket,(char*)buf,200*sizeof(wchar_t),0);
if(strLast<=0)
{//如果读取的长度不正常,退出循环。
break;
}
//倒数第三个参数为0,函数功能变为:返回buf的char类型容量。下面才好动态分配一个char*的内存空间。
DWORD charLen=WideCharToMultiByte(CP_UTF8,0,buf,-1,NULL,0,NULL,FALSE);
char* MutiByteBuf;
MutiByteBuf=new char[charLen];
WideCharToMultiByte(CP_UTF8,0,buf,-1,MutiByteBuf,charLen,NULL,FALSE);
xmlFile.Write(MutiByteBuf,charLen);
delete [] MutiByteBuf;
}while(strLast>0);
xmlFile.Close();
closesocket(theSocket);
WSACleanup();
}
过程很辛苦,但结果很简单。
TIP:WideCharToMultiByte的第四个参数为-1,那么第三个参数buf的长度就是buf内容长度+一个NULL。
就是因为加的这个NULL导致我的程序在第二次循环后,时不时的出现乱码,非常恼火。
下面是可以正常工作的代码。
void CTecClientDlg::OnBnClickedbtnlogin()
{
// TODO: 登陆按钮,登陆后下载数据。
WORD version;
WSADATA wsaData;
int rVal=0;
version=MAKEWORD(1,1);
WSAStartup(version,(LPWSADATA)&wsaData);
SOCKET theSocket=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
if(theSocket==SOCKET_ERROR)
{
return;
}
SOCKADDR_IN serverInfo;
serverInfo.sin_family=PF_INET;
serverInfo.sin_addr.s_addr=inet_addr("192.168.0.3");
serverInfo.sin_port=htons(6603);
rVal=connect(theSocket,(LPSOCKADDR)&serverInfo,sizeof(serverInfo));
if(rVal==SOCKET_ERROR)
{
return;
}
CFile xmlFile(_T("Data.xml"),CFile::modeCreate|CFile::modeWrite);
wchar_t buf[200];
int strLast=0;
do{
memset(buf,0,200*sizeof(wchar_t));
strLast=recv(theSocket,(char*)buf,200*sizeof(wchar_t),0);
if(strLast<=0)
{
break;
}
/**
*
*就是这个地方,第四个参数我没有使用-1,而是使用了精确的长度 strLast/2,这样就不会在末尾追加了。
*下面一处的调用也是一样的。
**/
DWORD charLen=WideCharToMultiByte(CP_UTF8,0,buf,strLast/2,NULL,0,NULL,FALSE);
char* MutiByteBuf;
MutiByteBuf=new char[charLen];
WideCharToMultiByte(CP_UTF8,0,buf,strLast/2,MutiByteBuf,charLen,NULL,FALSE);
xmlFile.Write(MutiByteBuf,charLen);
delete [] MutiByteBuf;
}while(strLast>0);
xmlFile.Close();
closesocket(theSocket);
WSACleanup();
}