1:windows版和linux版
#include <iostream>
#include <string>
#include <string.h>
#include <stdlib.h>
using namespace std;
int preNUm(unsigned char byte) {
unsigned char mask = 0x80;
int num = 0;
for (int i = 0; i < 8; i++) {
if ((byte & mask) == mask) {
mask = mask >> 1;
num++;
}
else {
break;
}
}
return num;
}
bool isUtf8(unsigned char* data, int len) {
int num = 0;
int i = 0;
while (i < len) {
if ((data[i] & 0x80) == 0x00) {
// 0XXX_XXXX
i++;
continue;
}
else if ((num = preNUm(data[i])) > 2) {
// 110X_XXXX 10XX_XXXX
// 1110_XXXX 10XX_XXXX 10XX_XXXX
// 1111_0XXX 10XX_XXXX 10XX_XXXX 10XX_XXXX
// 1111_10XX 10XX_XXXX 10XX_XXXX 10XX_XXXX 10XX_XXXX
// 1111_110X 10XX_XXXX 10XX_XXXX 10XX_XXXX 10XX_XXXX 10XX_XXXX
// preNUm() 返回首个字节8个bits中首�?0bit前面1bit的个数,该数量也是该字符所使用的字节数
i++;
for (int j = 0; j < num - 1; j++) {
//判断后面num - 1 个字节是不是都是10开
if ((data[i] & 0xc0) != 0x80) {
return false;
}
i++;
}
}
else {
//其他情况说明不是utf-8
return false;
}
}
return true;
}
bool isGBK(unsigned char* data, int len) {
int i = 0;
while (i < len) {
if (data[i] <= 0x7f) {
//编码小于等于127,只有一个字节的编码,兼容ASCII
i++;
continue;
}
else {
//大于127的使用双字节编码
if (data[i] >= 0x81 &&
data[i] <= 0xfe &&
data[i + 1] >= 0x40 &&
data[i + 1] <= 0xfe &&
data[i + 1] != 0xf7) {
i += 2;
continue;
}
else {
return false;
}
}
}
return true;
}
typedef enum {
GBK,
UTF8,
UNKOWN
} CODING;
//需要说明的是,isGBK()是通过双字节是否落在gbk的编码范围内实现的,
//而utf-8编码格式的每个字节都是落在gbk的编码范围内�?
//所以只有先调用isUtf8()先判断不是utf-8编码,再调用isGBK()才有意义
CODING GetCoding(unsigned char* data, int len) {
CODING coding;
if (isUtf8(data, len) == true) {
coding = UTF8;
}
else if (isGBK(data, len) == true) {
coding = GBK;
}
else {
coding = UNKOWN;
}
return coding;
}
#ifdef _WIN32
#include <windows.h>
string GbkToUtf8(const char *src_str)
{
int len = MultiByteToWideChar(CP_ACP, 0, src_str, -1, NULL, 0);
wchar_t* wstr = new wchar_t[len + 1];
memset(wstr, 0, len + 1);
MultiByteToWideChar(CP_ACP, 0, src_str, -1, wstr, len);
len = WideCharToMultiByte(CP_UTF8, 0, wstr, -1, NULL, 0, NULL, NULL);
char* str = new char[len + 1];
memset(str, 0, len + 1);
WideCharToMultiByte(CP_UTF8, 0, wstr, -1, str, len, NULL, NULL);
string strTemp = str;
if (wstr) delete[] wstr;
if (str) delete[] str;
return strTemp;
}
string Utf8ToGbk(const char *src_str)
{
int len = MultiByteToWideChar(CP_UTF8, 0, src_str, -1, NULL, 0);
wchar_t* wszGBK = new wchar_t[len + 1];
memset(wszGBK, 0, len * 2 + 2);
MultiByteToWideChar(CP_UTF8, 0, src_str, -1, wszGBK, len);
len = WideCharToMultiByte(CP_ACP, 0, wszGBK, -1, NULL, 0, NULL, NULL);
char* szGBK = new char[len + 1];
memset(szGBK, 0, len + 1);
WideCharToMultiByte(CP_ACP, 0, wszGBK, -1, szGBK, len, NULL, NULL);
string strTemp(szGBK);
if (wszGBK) delete[] wszGBK;
if (szGBK) delete[] szGBK;
return strTemp;
}
#else
#include <iconv.h>
int GbkToUtf8(char *str_str, size_t src_len, char *dst_str, size_t dst_len)
{
iconv_t cd;
char **pin = &str_str;
char **pout = &dst_str;
cd = iconv_open("utf8", "gbk");
if (cd == 0)
return -1;
memset(dst_str, 0, dst_len);
if (iconv(cd, pin, &src_len, pout, &dst_len) == -1)
return -1;
iconv_close(cd);
*pout = '\0';
return 0;
}
int Utf8ToGbk(char *src_str, size_t src_len, char *dst_str, size_t dst_len)
{
iconv_t cd;
char **pin = &src_str;
char **pout = &dst_str;
cd = iconv_open("gbk", "utf8");
if (cd == 0)
return -1;
memset(dst_str, 0, dst_len);
if (iconv(cd, pin, &src_len, pout, &dst_len) == -1)
return -1;
iconv_close(cd);
*pout = '\0';
return 0;
}
#endif
int main(void)
{
char *src_str = "hello,你好撒大沙发,这里是科大讯飞啊撒旦飞洒发大师傅撒犯得上发生";
cout << "origin string: " << src_str << endl;
cout << "GetCoding: " << GetCoding((unsigned char*)src_str, strlen(src_str)) << endl;
#ifdef _WIN32
string dst_str = Utf8ToGbk(src_str);
cout << "utf8 to gbk: " << dst_str << endl;
string str_utf8 = GbkToUtf8(dst_str.c_str());
cout << "gbk to utf: " << str_utf8 << endl;
#else
// unix default is utf8
char dst_gbk[1024] = { 0 };
Utf8ToGbk(src_str, strlen(src_str), dst_gbk, sizeof(dst_gbk));
cout << "utf8 to gbk: " << dst_gbk << endl;
char dst_utf8[1024] = { 0 };
GbkToUtf8(dst_gbk, strlen(dst_gbk), dst_utf8, sizeof(dst_utf8));
cout << "gbk to utf8: " << dst_utf8 << endl;
#endif
system("pause");
return 0;
}
2:c++11 版windows和linux
#include <iostream>
#include <string>
#include <string.h>
#include <stdlib.h>
#include <locale>
#include <codecvt>
using namespace std;
int preNUm(unsigned char byte) {
unsigned char mask = 0x80;
int num = 0;
for (int i = 0; i < 8; i++) {
if ((byte & mask) == mask) {
mask = mask >> 1;
num++;
}
else {
break;
}
}
return num;
}
bool isUtf8(unsigned char* data, int len) {
int num = 0;
int i = 0;
while (i < len) {
if ((data[i] & 0x80) == 0x00) {
// 0XXX_XXXX
i++;
continue;
}
else if ((num = preNUm(data[i])) > 2) {
// 110X_XXXX 10XX_XXXX
// 1110_XXXX 10XX_XXXX 10XX_XXXX
// 1111_0XXX 10XX_XXXX 10XX_XXXX 10XX_XXXX
// 1111_10XX 10XX_XXXX 10XX_XXXX 10XX_XXXX 10XX_XXXX
// 1111_110X 10XX_XXXX 10XX_XXXX 10XX_XXXX 10XX_XXXX 10XX_XXXX
// preNUm() 返回首个字节8个bits中首�?0bit前面1bit的个数,该数量也是该字符所使用的字节数
i++;
for (int j = 0; j < num - 1; j++) {
//判断后面num - 1 个字节是不是都是10开
if ((data[i] & 0xc0) != 0x80) {
return false;
}
i++;
}
}
else {
//其他情况说明不是utf-8
return false;
}
}
return true;
}
bool isGBK(unsigned char* data, int len) {
int i = 0;
while (i < len) {
if (data[i] <= 0x7f) {
//编码小于等于127,只有一个字节的编码,兼容ASCII
i++;
continue;
}
else {
//大于127的使用双字节编码
if (data[i] >= 0x81 &&
data[i] <= 0xfe &&
data[i + 1] >= 0x40 &&
data[i + 1] <= 0xfe &&
data[i + 1] != 0xf7) {
i += 2;
continue;
}
else {
return false;
}
}
}
return true;
}
typedef enum {
GBK,
UTF8,
UNKOWN
} CODING;
//需要说明的是,isGBK()是通过双字节是否落在gbk的编码范围内实现的,
//而utf-8编码格式的每个字节都是落在gbk的编码范围内�?
//所以只有先调用isUtf8()先判断不是utf-8编码,再调用isGBK()才有意义
CODING GetCoding(unsigned char* data, int len) {
CODING coding;
if (isUtf8(data, len) == true) {
coding = UTF8;
}
else if (isGBK(data, len) == true) {
coding = GBK;
}
else {
coding = UNKOWN;
}
return coding;
}
string GbkToUtf8(const std::string& str)
{
#ifdef _WIN32
//GBK locale name in windows
const char* GBK_LOCALE_NAME = ".936";
#else
//GBK locale name in linux
const char* GBK_LOCALE_NAME = "zh_CN.GBK";
#endif
std::wstring_convert<std::codecvt_byname<wchar_t, char, mbstate_t>> convert(new std::codecvt_byname<wchar_t, char, mbstate_t>(GBK_LOCALE_NAME));
std::wstring tmp_wstr = convert.from_bytes(str);
std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> cv2;
return cv2.to_bytes(tmp_wstr);
}
string Utf8ToGbk(const std::string& str)
{
std::wstring_convert<std::codecvt_utf8<wchar_t> > conv;
std::wstring tmp_wstr = conv.from_bytes(str);
#ifdef _WIN32
//GBK locale name in windows
const char* GBK_LOCALE_NAME = ".936";
#else
//GBK locale name in linux
const char* GBK_LOCALE_NAME = "zh_CN.GBK";
#endif
std::wstring_convert<std::codecvt_byname<wchar_t, char, mbstate_t>> convert(new std::codecvt_byname<wchar_t, char, mbstate_t>(GBK_LOCALE_NAME));
return convert.to_bytes(tmp_wstr);
}
int main(void)
{
std::string src_str = "hello,你好撒大沙发,这里是科大讯飞啊撒旦飞洒发大师傅撒犯得上发生";
cout << "origin string: " << src_str << endl;
cout << "GetCoding: " << GetCoding((unsigned char*)src_str.c_str(), src_str.length()) << endl;
#ifdef _WIN32
string dst_str = Utf8ToGbk(src_str);
cout << "utf8 to gbk: " << dst_str << endl;
string str_utf8 = GbkToUtf8(dst_str.c_str());
cout << "gbk to utf: " << str_utf8 << endl;
system("pause");
return 0;
}