使用EasyX製作遊戲需要讀寫檔案時遇到編碼問題的解決方法
一、編碼問題
例如我們需要從file.txt中讀取文字,再使用outtextxy()
函式向視窗繪製文字。
查詢EasyX的官方文件可知,該函式有兩個過載,分別為:void outtextxy(int x, int y, LPCTSTR str)
和void outtextxy(int x, int y, TCHAR c)
。
如果我們的file.txt檔案使用GBK或者GB2312編碼的話,會導致VS編譯器混合utf-8編碼和GBK編碼,導致程式不能正確繪製文字。
編碼問題一直是令人頭痛的問題,這裡給出通用的方法論,希望能夠帶來一些幫助。
二、解決方法
1.重新編碼txt檔案
首先使用vscode開啟file.txt檔案,確保檔案編碼為utf-8。如下圖:
如果不是utf-8編碼,點選選擇編碼,透過編碼重新開啟,選擇utf-8編碼,這時原來的內容會變成亂碼,將原來的內容刪除,重新輸入,儲存即可。具體的操作如下圖:
2.程式碼部分
首先,我們需要用到std::wstring_convert
,這個標準庫需要標頭檔案#include<codecvt>
,我們定義string str
,用static std::wstring_convert<std::codecvt_utf8<wchar_t>, wchar_t> converter;
定義我們所需要的從utf-8編碼的字串到寬字串的轉換器。
開啟檔案,讀取檔案內容到str內,使用from_bytes(str)
函式即可實現字串的轉換,又由於outtextxy沒有使用wstring的過載,使用wstring的成員函式c_str()
即可轉換成wchar_t
字串,最終,我們用這樣的程式碼將文字繪製在視窗上outtextxy(10, 10, converter.from_bytes(str).c_str());
。
效果如圖:
完整程式碼如下:
#include<fstream>
#include<codecvt>
#include<string>
#include<iostream>
#include<graphics.h>
std::string str;
int main()
{
initgraph(500, 500);
static std::wstring_convert<std::codecvt_utf8<wchar_t>, wchar_t> converter;
std::ifstream infile("file.txt");
if (!infile)
{
std::cerr << "無法開啟檔案" << std::endl;
return 0;
}
std::getline(infile, str);
infile.close();
while (true)
{
outtextxy(10, 10, converter.from_bytes(str).c_str());
}
}
三、問題延伸
如果我們需要在程式內使用InputBox
對話方塊輸入,並將輸入的內容正確儲存在檔案裡,該如何操作呢。
首先檢視InputBox
的引數列表bool InputBox(LPTSTR pString, int nMaxCount, LPCTSTR pPrompt = NULL, LPCTSTR pTitle = NULL, LPCTSTR pDefault = NULL, int width = 0, int height = 0, bool bOnlyOK = true);
,其中大部分是預設引數,這裡不做解釋,重點是第一個引數,InputBox
只接受&wchar_t
的引數,因此,假設輸入的字串最大長度為256,我們定義TCHAR buffer[256];
陣列來接收輸入,寫下這樣的程式碼來彈出對話方塊InputBox(buffer, 256, _T("請輸入:"), _T("輸入框"), NULL, 0, 0, TRUE);
開啟檔案,定義std::string str;
,仍然使用我們剛才定義的轉換器,使用to_bytes()
函式,即可將輸入的內容轉換為utf-8字串。再進行輸入即可。
完整程式碼如下:
#include<fstream>
#include<codecvt>
#include<string>
#include<iostream>
#include<graphics.h>
int main()
{
initgraph(500, 500);
static std::wstring_convert<std::codecvt_utf8<wchar_t>, wchar_t> converter;
TCHAR buffer[256];
InputBox(buffer, 256, _T("請輸入:"), _T("輸入框"), NULL, 0, 0, TRUE);
std::ofstream outfile("file.txt");
if (!outfile)
{
std::cerr << "無法開啟檔案" << std::endl;
return 0;
}
std::string str = converter.to_bytes(buffer);
outfile << str;
outfile.close();
}