記錄MFC在UNICODE字符集下讀取中ANSI英文混合文件英文字符為單數漢字出現亂碼問題


  慚愧,做了3年多 C++ 了,雖說半路出家,之前也做過 Linux 一年多,但是 MFC 也做了一年多了,由於一直維護公司的老項目,也沒有做過新東西。

  最近心血來潮,在網上找了些學習視頻,復習下 MFC 控件的使用,熟悉下 MFC 的 API,畢竟是吃飯的家伙,廢話不多說,來干貨。

  最近在仿寫一個記事本軟件,初具基本功能,但遇到了一個比較蹩腳的問題,MFC 在 UNICODE 字符集下在讀取 ANSI 編碼的文本文件時,全中文沒問題,全英文也沒問題,但是中英文混合時,當英文個數為奇數個時,英文后面的漢字就會編程亂碼。

  原因是我想的太簡單了,覺得讀取 ANSI 編碼的文本文件,就是讀取多字節字符串,也就有了如下代碼:

  代碼中的形參只是定義了一個 CFile 對象並以只讀方式打開,個人習慣,如果解釋就要解釋的明明白白,所以給這兩句代碼也復制過來了。

  CFile file;
  file.Open(szFile, CFile::modeRead);

 1 void CNotepadDlg::ReadAnsi(CFile& file)
 2 {
 3     file.Seek(0, CFile::begin);
 4     char buff[1024];
 5     UINT nRet = 0;
 6     CString str;
 7 
 8     while (nRet = file.Read(buff, sizeof(buff - 1)))
 9     {
10         buff[nRet] = '\0';
11         str += buff;
12     }
13 
14     SetDlgItemText(IDC_EDIT_TEXT, str);
15 
16 }

  這只是按照單字節讀取,當然顯示也就存在問題。

  這是用微軟記事本打開的 ANSI 編碼的文本文檔。

 

 

   這是我仿寫記事本打開的文本文檔

 

 

  結果很明顯,不對。

  網上也找了很多處理辦法,A2T,bstr_t,_tsetlocale(LC_ALL, _T("chs")); 這幾個方法都試了,可能我水平不濟,確實沒弄明白,最后還是用最原始的 MultiByteToWideChar() 解決了問題。當然,代碼還存在許多問題,待優化。

  

 1 void CMFC194Dlg::ReadAnsi(CFile& file)
 2 {
 3     file.Seek(0, CFile::begin);
 4     // TODO: 在此處添加實現代碼.
 5     char buff[1024];
 6     UINT nRet = 0;
 7     CString str;
 8     
 9     LONGLONG nLen = file.GetLength();
10     char* p = new char[nLen + 1];
11     nLen = file.Read(p, nLen);
12     p[nLen] = '\0';
13     TCHAR* pText = new TCHAR[nLen + 2];
14     memset(pText,0 , nLen + 2);
15 
16     nLen = MultiByteToWideChar(CP_ACP, NULL, p, -1, pText, nLen + 2);
17 
18     SetDlgItemText(IDC_EDIT_TEXT, pText);
19 
20     delete[]p;
21     delete[]pText;
22 }

  讀取結果:

 

  處理這個問題的靈魂是這兩句代碼:

  TCHAR* pText = new TCHAR[nLen + 2];

  memset(pText,0 , nLen + 2);

  因為 ANSI 編碼中英文字母占一個字節,中文漢字占兩個字節,所以定義 pText 長度不能是 多字節長度 / 2 + 2,這會導致空間不足,使 MultiByteToWideChar() 返回 0,用 GetLastError() 可知返回122。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM