在用MFC编写一个上位机时,需要实现选择和读取一个二进制文件,本来以为很简单的但是在实现过程中遇到很多问题,所幸都一一解决,这里做一下记录。
首先在实现文件选择,在界面上设置一个按钮,并在点击事件函数中输入以下:
1 void CWeatherStationDlg::OnBnClickedButton6()//选择文件 2 { 3 // TODO: 在此添加控件通知处理程序代码 4 m_strHistoryPath = "";//文件选择清空 5 CFileDialog dlg(TRUE,_T("txt"),NULL,OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT,_T("文本文件|*.txt||")); 6 if (dlg.DoModal()==IDOK) 7 { 8 m_strHistoryPath = dlg.GetPathName(); 9 if (m_strHistoryPath == "") 10 { 11 MessageBox(_T("未选择文件!")); 12 return; 13 } 14 } 15 ((CEdit*)GetDlgItem(IDC_EDIT5))->SetWindowText(m_strHistoryPath); 16 17 }
然后实现了文件选择,此时文件路径保存在 CString m_strHistoryPath中。然后需要打开改文件,这里采用了fopen打开,需要将CString 格式转为char *格式,先采用强制类型转换:
FILE *fReadHistory = NULL;char *cReadHis;cReadHis=(char*)malloc(200*sizeof(char)); cReadHis= (LPSTR)(LPCTSTR)m_strHistoryPath; fReadHistory = fopen(cReadHis, "rb");fread(strStarLine,1,1,fReadHistory);
此时fread中始终没有数据读入,后来经过查找了解由于当前编译环境为 Unicode,CString 实际上是 CSringW,虽然强转成了 const char *,但你实际发出去的字符串是 "A\0B\0C\0"六个字节。
后来又采用了WideCharToMultiByte();
1 FILE *fReadHistory = NULL; 2 char *cReadHis; 3 cReadHis=(char*)malloc(200*sizeof(char)); 4 memset(cReadHis,0,sizeof(cReadHis)); 5 int n = m_strHistoryPath.GetLength(); //获取宽字节字符的大小,大小是按字节计算的 6 int len = WideCharToMultiByte(CP_ACP,0,m_strHistoryPath,m_strHistoryPath.GetLength(),NULL,0,NULL,NULL); 7 WideCharToMultiByte(CP_ACP,0,m_strHistoryPath,m_strHistoryPath.GetLength(),cReadHis,len,NULL,NULL); 8 cReadHis[len+1]='/0'; //多字节字符以'/0'结束 9 10 fReadHistory = fopen(cReadHis, "rb");
但是此时cReadHis后面存在乱码,导致文件无法打开。
又经过查找文件了解
WideCharToMultiByte(CP_ACP,0,m_strHistoryPath,m_strHistoryPath.GetLength(),cReadHis,len,NULL,NULL);
应改为
WideCharToMultiByte(CP_ACP,0,m_strHistoryPath,m_strHistoryPath.GetLength()+1,cReadHis,len+1,NULL,NULL);
此时路径就正常了,文件也能正常读入。原因暂时还未深究。
此时再补充一点,在程序编写时输入文件读取地址一定不能用单斜杆“\”,需要改为反向单斜杆“/”或双斜杠“\\”,但是用文件选择CFileDialog 读入路径时是不受影响的,内部已经进行过转义。我在这里纠结过很长时间,发现其实不是这里的问题。