# C++/CLI WinForm 讀取文字檔亂碼問題 ###### tags: `C++/CLI`, `問題記錄`, `lab 專案` ## 📌 **問題描述** ➡️ 目標 已寫好 WinForm (.h) 會將 user 選取的文字 (含有中文) 儲存為 .txt 希望在 .cpp 讀取 .txt 中的文字,並跟 .cpp 的指定文字比較 但讀取到的東西是亂碼,也無法比較文字是否相同 ➡️ 1. 存檔方式 .h 的 UI 按鈕事件觸發後,將下拉按鈕(ComboBox)選中的文字儲存為 .txt 檔案 ➡️ 2. 讀檔有亂碼 .cpp 讀出的文字檔是亂碼 而且無法與指定的文字 compare ## 📌 **原因** ➡️ 1. C++ 字串的資料型態: string or wstring WinForm 的文字是 wstring 負責後續 "文字比較" 的程式中,指定文字卻是用 string 這樣就會有問題 必須將文字皆轉成 wstring ➡️ 2. 編碼(encoding)問題 - txt 檔的編碼是 UTF-8 > 補充 > windows 以前 txt 檔的預設編碼是 ANSI > windows 10 之後預設編碼統一改成 UTF-8 > (UTF-8 編碼可顯示部分的中文 > 但不包含所有中文繁/簡字體 > 所以有時候會出現亂碼問題) - C++ 程式可接受的字串編碼只有 ANSI 和 Unicode - console 預設顯示的編碼是 ANSI > 上述的 3 個階段的編碼方式若不相同 > 在沒做處理的情況下就會看到亂碼 ## 📌 **解決方式** ➡️ Method 1. 手動修改編碼方式 開啟文字檔 > 檔案 > 另存檔案 | 編碼: ANSI > 儲存 ➡️ Method 2. 寫一個 function (Standard C++) 放在 .cpp 中 先將 txt 讀出文字的編碼從 UTF-8 轉 Unicode,並轉型為 wstring > .cpp 檔案的 string 變數就是 Unicode 不需再處理 再以 wstring 指定 "欲比較文字" (用在 if branch 的判斷邏輯) 最後比較兩個 wstring 是否相同 ``` bool compareTxtFileStrAndLocalStr(string txtFileStr, wstring localWStr) { // txtFileStr: 儲存在 txt 檔的文字 (UTF-8) // localStr: 目前程式區塊指定的文字 (Unicode) // 將 txtFileStr 的編碼從 UTF-8 轉成 Unicode, 並轉為 wstring , 暫存在 txtFileWStrUni wstring txtFileWStrUni; wchar_t txtFileWCharArrUni[1024]; char* charArrUtf8 = new char[txtFileStr.length() + 1]; strcpy(charArrUtf8, txtFileStr.c_str()); MultiByteToWideChar(CP_UTF8, 0, charArrUtf8, -1, txtFileWCharArrUni, (int)strlen(charArrUtf8) * 2); txtFileWStrUni = txtFileWCharArrUni; // 比較兩個 wstring 是否相同 bool isWStrEqual; transform(txtFileWStrUni.begin(), txtFileWStrUni.end(), txtFileWStrUni.begin(), toupper); transform(localWStr.begin(), localWStr.end(), localWStr.begin(), toupper); return (txtFileWStrUni == localWStr); } ``` ## 📌 **參考資料** 1. C++ -讀取 txt 文字檔 中文亂碼問題 https://husking-studio.com/cpp-txt-file-01/ 2. Read Unicode UTF-8 file into wstring https://stackoverflow.com/questions/4775437/read-unicode-utf-8-file-into-wstring