C ++ jsoncpp中国語と\ uXXXXは、toStyledStringを使用して文字列中国語の文字化けソリューションを生成します

目次

1.中国の文字化けしたソリューション

1.1、文字化けしたディスプレイ

1.2。コードが文字化けしている理由と解決策

次に、\ uXXXX解析を含む文字化けしたコードの解決策

2.1、文字化けしたディスプレイ

2.2文字化​​けの理由

2.3。解決策


1.中国の文字化けしたソリューション

1.1、文字化けしたディスプレイ

jsoncppを使用して中国語を含む文字列を解析する場合、toStyledString()関数によって生成された文字列の中国語部分は\ uに4桁の16進数を加えたものになり、文字化けした解析が発生します。

といった:

1.2。コードが文字化けしている理由と解決策

jsoncppのソースコードを分析するには(公式ダウンロードアドレス:http://sourceforge.net/projects/jsoncpp/files/  )。StyledWriterのwriteValue関数を分析すると、文字列の処理がvalueToQuotedStringN関数によってエスケープされていることがわかります。

static String valueToQuotedStringN(const char* value, unsigned length) {
  if (value == nullptr)
    return "";

  if (!isAnyCharRequiredQuoting(value, length))
    return String("\"") + value + "\"";
  // We have to walk value and escape any special characters.
  // Appending to String is not efficient, but this should be rare.
  // (Note: forward slashes are *not* rare, but I am not escaping them.)
  String::size_type maxsize = length * 2 + 3; // allescaped+quotes+NULL
  String result;
  result.reserve(maxsize); // to avoid lots of mallocs
  result += "\"";
  char const* end = value + length;
  for (const char* c = value; c != end; ++c) {
    switch (*c) {
    case '\"':
      result += "\\\"";
      break;
    case '\\':
      result += "\\\\";
      break;
    case '\b':
      result += "\\b";
      break;
    case '\f':
      result += "\\f";
      break;
    case '\n':
      result += "\\n";
      break;
    case '\r':
      result += "\\r";
      break;
    case '\t':
      result += "\\t";
      break;
    // case '/':
    // Even though \/ is considered a legal escape in JSON, a bare
    // slash is also legal, so I see no reason to escape it.
    // (I hope I am not misunderstanding something.)
    // blep notes: actually escaping \/ may be useful in javascript to avoid </
    // sequence.
    // Should add a flag to allow this compatibility mode and prevent this
    // sequence from occurring.
	default: {
		unsigned int cp = utf8ToCodepoint(c, end);
		// don't escape non-control characters
		// (short escape sequence are applied above)
		if (cp < 0x80 && cp >= 0x20)
			result += static_cast<char>(cp);
		else if (cp < 0x10000) { // codepoint is in Basic Multilingual Plane
			result += "\\u";
			result += toHex16Bit(cp);
		}
		else { // codepoint is not in Basic Multilingual Plane
			   // convert to surrogate pair first
			cp -= 0x10000;
			result += "\\u";
			result += toHex16Bit((cp >> 10) + 0xD800);
			result += "\\u";
			result += toHex16Bit((cp & 0x3FF) + 0xDC00);
		}

		}break;
	}
  }
  result += "\"";
  return result;
}

コードを通して、default:が漢字を含む文字を処理することがはっきりとわかります。したがって、ソースコードを変更してライブラリを再コンパイルできます。意志:

	default: {
		unsigned int cp = utf8ToCodepoint(c, end);
		// don't escape non-control characters
		// (short escape sequence are applied above)
		if (cp < 0x80 && cp >= 0x20)
			result += static_cast<char>(cp);
		else if (cp < 0x10000) { // codepoint is in Basic Multilingual Plane
			result += "\\u";
			result += toHex16Bit(cp);
		}
		else { // codepoint is not in Basic Multilingual Plane
			   // convert to surrogate pair first
			cp -= 0x10000;
			result += "\\u";
			result += toHex16Bit((cp >> 10) + 0xD800);
			result += "\\u";
			result += toHex16Bit((cp & 0x3FF) + 0xDC00);
		}

			//result += *c;
			
		}break;

に:

	default: {
			result += *c;
    }break;

最終結果は次のとおりです。

参照リンク:

C ++ jsoncppは、toStyledStringを使用して、文字列の中国語の文字化けソリューションを生成します

次に、\ uXXXX解析を含む文字化けしたコードの解決策

2.1、文字化けしたディスプレイ

jsonファイルは次のとおりです。

分析結果:

2.2文字化​​けの理由

valueToQuotedStringN関数は以前に変更されています。この関数は文字列をUnicodeエンコーディングに変換するため、\ uXXXX形式で直接読み取られる文字列は実際にはutf-8文字列(中国語を読んでいる場合はUnicodeエンコーディング)です。したがって、ここでは、文字列をUnicodeコードに追加変換する必要があります

2.3。解決策

utf-8からUnicodeへ:

wstring UTF8ToUnicode(const string& str)
{
	int len = 0;
	len = str.length();
	int unicodeLen = ::MultiByteToWideChar(CP_UTF8,
		0,
		str.c_str(),
		-1,
		NULL,
		0);
	wchar_t * pUnicode;
	pUnicode = new wchar_t[unicodeLen + 1];
	memset(pUnicode, 0, (unicodeLen + 1) * sizeof(wchar_t));
	::MultiByteToWideChar(CP_UTF8,
		0,
		str.c_str(),
		-1,
		(LPWSTR)pUnicode,
		unicodeLen);
	wstring rt;
	rt = (wchar_t*)pUnicode;
	delete pUnicode;
	return rt;
}

この関数をプログラムに追加して、次を呼び出します。

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;
}


//调用
std::string content = root["Cnki"][i]["content"].toStyledString();
wstring wstr = UTF8ToUnicode(content);//将utf-8转化为unicode格式	
cout << ws2s(wstr) << endl;	

結果:

参照リンク:

C ++ STRINGとWSTRINGの間の変換関数

おすすめ

転載: blog.csdn.net/wxplol/article/details/109505854