1. 程式人生 > 其它 >TSINGSEE青犀視訊開發AI智慧分析採用c++中文編碼出現亂碼問題是由什麼導致的

TSINGSEE青犀視訊開發AI智慧分析採用c++中文編碼出現亂碼問題是由什麼導致的

EasyCVR的AI智慧分析版本在做研發的時候,就受到了很多朋友的關注,EasyCVR的人臉識別功能採用了Go語言,使用c/c++ 的標頭檔案和dll檔案。在C++ 中如果出現中文,會出現亂碼的問題,使用notepad++開啟儲存的二進位制檔案,出現亂碼。

正常的情況選擇UTF8編碼正常顯示:

在計算機的內部,所有的資料都是以二進位制的形式儲存的,在儲存文字時,需要將文字檔案的資訊都轉換為二進位制進行儲存,而現實是將二進位制轉換為文字顯示,所以編碼就是以二進位制和顯示字元直接轉換。

  • ASCII碼:是美國製定的一套字元編碼,主要用來顯示英文字元。
  • GBK:ASCII編碼只適合顯示英文字元,但是對中文有6000多個常用漢字,一個位元組的大小完全不夠用。所以制定GBK標準。用二個位元組來表示中文。
  • ASNI:除了中國以外,其他的許多國家頁都制定自己的編碼標準。
  • Unicode:由於不同的ANSI編碼之間互不相容,這樣進行資訊互動就會進行編碼轉換。為了解決這個問題,又制定Unicode編碼,用二個位元組統一表示所有字元。
  • UTF-8:Unicode可以表示所有的字元,但是英文字元也與其他字元一樣,使用兩個位元組進行編碼,使得在儲存英文文字的時候會多出一倍的儲存空間,而大多數的文字資訊都是英文的。所以UTF-8是一種可變長的編碼方式。

多位元組到寬位元組的轉換:

setlocale(LC_ALL, "");
	size_t requiredSize = mbstowcs(nullptr, w, 0);
	wszClassName = new WCHAR[requiredSize + 1];
	memset(wszClassName, 0x00, sizeof(wszClassName));
	if (static_cast<size_t>(-1) == mbstowcs(wszClassName, w, requiredSize + 1))
	{
		std::cout << "fail" << std::endl;
		return -1;
	}
	else
	{
		std::wcout << "success: " << wszClassName << std::endl;
	}
return 0;
複製程式碼

UTF-8編碼轉GBK,在vs中列印輸出:

std::wstring UT2WC(const char* buf)
{
	int len = MultiByteToWideChar(CP_UTF8, 0, buf, -1, NULL, 0);
	std::vector<wchar_t> unicode(len);
	MultiByteToWideChar(CP_UTF8, 0, buf, -1, &unicode[0], len);

	return std::wstring(&unicode[0]);
}

std::string ws2s(const std::wstring& ws)
{
	std::string curLocale = setlocale(LC_ALL, NULL);
	setlocale(LC_ALL, "chs");
	const wchar_t* _Source = ws.c_str();
	size_t _Dsize = 2 * ws.size() + 1;
	char *_Dest = new char[_Dsize];
	memset(_Dest, 0, _Dsize);
	wcstombs(_Dest, _Source, _Dsize);
	std::string result = _Dest;
	delete[]_Dest;
	setlocale(LC_ALL, curLocale.c_str());
	return result;
}
複製程式碼

Unicode、ANSI和UTF之間的轉換:

std::string UnicodeToUTF8(const std::wstring & wstr)
{
	std::string ret;
	try {
		std::wstring_convert< std::codecvt_utf8<wchar_t> > wcv;
		ret = wcv.to_bytes(wstr);
	}
	catch (const std::exception & e) {
		std::cerr << e.what() << std::endl;
	}
	return ret;
}

std::wstring UTF8ToUnicode(const std::string & str)
{
	std::wstring ret;
	try {
		std::wstring_convert< std::codecvt_utf8<wchar_t> > wcv;
		ret = wcv.from_bytes(str);
	}
	catch (const std::exception & e) {
		std::cerr << e.what() << std::endl;
	}
	return ret;
}

std::string UnicodeToANSI(const std::wstring & wstr)
{
	std::string ret;
	std::mbstate_t state = {};
	const wchar_t *src = wstr.data();
	size_t len = std::wcsrtombs(nullptr, &src, 0, &state);
	if (static_cast<size_t>(-1) != len) {
		std::unique_ptr< char[] > buff(new char[len + 1]);
		len = std::wcsrtombs(buff.get(), &src, len, &state);
		if (static_cast<size_t>(-1) != len) {
			ret.assign(buff.get(), len);
		}
	}
	return ret;
}

std::wstring ANSIToUnicode(const std::string & str)
{
	std::wstring ret;
	std::mbstate_t state = {};
	const char *src = str.data();
	size_t len = std::mbsrtowcs(nullptr, &src, 0, &state);
	if (static_cast<size_t>(-1) != len) {
		std::unique_ptr< wchar_t[] > buff(new wchar_t[len + 1]);
		len = std::mbsrtowcs(buff.get(), &src, len, &state);
		if (static_cast<size_t>(-1) != len) {
			ret.assign(buff.get(), len);
		}
	}
	return ret;
}

作者:TSINGSEE
連結:https://juejin.cn/post/7041806412866912292/
來源:稀土掘金
著作權歸作者所有。商業轉載請聯絡作者獲得授權,非商業轉載請註明出處。