在用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 讀入路徑時是不受影響的,內部已經進行過轉義。我在這里糾結過很長時間,發現其實不是這里的問題。