# 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