mysql跨平台乱码问题和mysql锁(未完待续9/27)

本文介绍了MySQL在Windows和Linux环境下关于GBK与UTF8字符集的转换方法,包括STL、Windows API及Linux接口的转换方式,并提供了相关代码示例。此外,还涉及了数据库、表和字段的编码设置,以及Visual Studio和Qt Creator的默认编码情况。
摘要由CSDN通过智能技术生成

0.大体mysql中文背景知识

①window平台只能显示gbk格式的,GBK和GB2312是比较类似的,但是GBK用的编码比较多,这两个都是基于阿斯克码ASCII,不过它们是两个阿斯克码存储一个汉字,(高级语言用GBK)
②linux的ssh控制台只能显示utf的,1或2或3或4字节表示汉字,变长的字节数
③Unicode编码格式是固定的,windows中都只用两个字节触发,linux中用utf-32 UCS-4
④vs2015之前,默认使用GBK
⑤qtcreator,默认使用utf-8
⑥vs2017默认utf-8
在这里插入图片描述

1.字符编码类型mysql设置和转换API分析

编码设置选择

①数据库编码可以设定
②表默认编码
③字段编码设置

转换API分析

转换方式一:STL
  • 总体概况
    在这里插入图片描述

  • 额外涉及到的问题:

①2015-2017和2013和gcc兼容的版本不一样,不兼容
②gbk转码涉及到std::locate,std::locate使用的话涉及到本地的字符集,如果ubantu中没装中文,那么转码就会失败(环境依赖度非常高)
③但是只有一个平台就没问题

转换方式二:Windows
  • 大体概况(MultiByteToWideChar多字节到宽字节的转换)

在这里插入图片描述

转换方式三:linux接口

在这里插入图片描述

  • 注意:

linux中转换gbk,返回值不是字节数,还好可以通过strlen获取字节数也能解决这个问题

2.windows上字符集gbk和utf8互转 和linux上字符集GBK和UTF8互转

头文件

#ifdef _WIN32
#include <windows.h> 
#else
#include <iconv.h>
#endif

#ifndef LXDATA_H
#define LXDATA_H

#ifdef _WIN32  //32 &64
	#ifdef LXMYSQL_EXPORTS
	//动态链接库项目调用
	#define LXAPI  __declspec(dllexport)
	#else
	//执行程序调用
	#define LXAPI  __declspec(dllimport)
	#endif
#else  //linux mac
	#define LXAPI
#endif


#include <map>
#include <string>
#include <string.h>
namespace LX 
{
	enum LX_OPT {
		LX_OPT_CONNECT_TIMEOUT,
		LX_OPT_COMPRESS,
		LX_OPT_NAMED_PIPE,
		LX_INIT_COMMAND,
		LX_READ_DEFAULT_FILE,
		LX_READ_DEFAULT_GROUP,
		LX_SET_CHARSET_DIR,
		LX_SET_CHARSET_NAME,
		LX_OPT_LOCAL_INFILE,
		LX_OPT_PROTOCOL,
		LX_SHARED_MEMORY_BASE_NAME,
		LX_OPT_READ_TIMEOUT,
		LX_OPT_WRITE_TIMEOUT,
		LX_OPT_USE_RESULT,
		LX_REPORT_DATA_TRUNCATION,
		LX_OPT_RECONNECT,
		LX_PLUGIN_DIR,
		LX_DEFAULT_AUTH,
		LX_OPT_BIND,
		LX_OPT_SSL_KEY,
		LX_OPT_SSL_CERT,
		LX_OPT_SSL_CA,
		LX_OPT_SSL_CAPATH,
		LX_OPT_SSL_CIPHER,
		LX_OPT_SSL_CRL,
		LX_OPT_SSL_CRLPATH,
		LX_OPT_CONNECT_ATTR_RESET,
		LX_OPT_CONNECT_ATTR_ADD,
		LX_OPT_CONNECT_ATTR_DELETE,
		LX_SERVER_PUBLIC_KEY,
		LX_ENABLE_CLEARTEXT_PLUGIN,
		LX_OPT_CAN_HANDLE_EXPIRED_PASSWORDS,
		LX_OPT_MAX_ALLOWED_PACKET,
		LX_OPT_NET_BUFFER_LENGTH,
		LX_OPT_TLS_VERSION,
		LX_OPT_SSL_MODE,
		LX_OPT_GET_SERVER_PUBLIC_KEY,
		LX_OPT_RETRY_COUNT,
		LX_OPT_OPTIONAL_RESULTSET_METADATA,
		LX_OPT_SSL_FIPS_MODE
	};
 
	enum FIELD_TYPE {
		LX_TYPE_DECIMAL,
		LX_TYPE_TINY,
		LX_TYPE_SHORT,
		LX_TYPE_LONG,
		LX_TYPE_FLOAT,
		LX_TYPE_DOUBLE,
		LX_TYPE_NULL,
		LX_TYPE_TIMESTAMP,
		LX_TYPE_LONGLONG,
		LX_TYPE_INT24,
		LX_TYPE_DATE,
		LX_TYPE_TIME,
		LX_TYPE_DATETIME,
		LX_TYPE_YEAR,
		LX_TYPE_NEWDATE, /**< Internal to MySQL. Not used in protocol */
		LX_TYPE_VARCHAR,
		LX_TYPE_BIT,
		LX_TYPE_TIMESTAMP2,
		LX_TYPE_DATETIME2, /**< Internal to MySQL. Not used in protocol */
		LX_TYPE_TIME2,     /**< Internal to MySQL. Not used in protocol */
		LX_TYPE_JSON = 245,
		LX_TYPE_NEWDECIMAL = 246,
		LX_TYPE_ENUM = 247,
		LX_TYPE_SET = 248,
		LX_TYPE_TINY_BLOB = 249,
		LX_TYPE_MEDIUM_BLOB = 250,
		LX_TYPE_LONG_BLOB = 251,
		LX_TYPE_BLOB = 252,
		LX_TYPE_VAR_STRING = 253,
		LX_TYPE_STRING = 254,
		LX_TYPE_GEOMETRY = 255
	} ;

	struct LXAPI LXData
	{
		LXData(const char* data=0);
		LXData(const int *d);
		//读取文件,内容写入到data,size大小 ,会在堆中申请data的空间,需要用Drop释放
		bool LoadFile(const char* filename);
		bool SaveFile(const char * filename);
		const char * data = 0;
		int size = 0;
		FIELD_TYPE type;
		//释放LoadFile申请的data空间
		void Drop();
		std::string UTF8ToGBK();
		std::string GBKToUTF8();

	};

	//插入和更新数据的数据结构
	typedef std::map <std::string, LXData> XDATA;
}

#endif

gbk转utf-8

#ifndef _WIN32
static size_t Convert(char *from_cha, char *to_cha, char *in, size_t inlen, char *out, size_t outlen)
{
	//转换上下文
	iconv_t cd;
	cd = iconv_open(to_cha, from_cha);
	if (cd == 0)
		return -1;
	memset(out, 0, outlen);
	char **pin = &in;
	char **pout = &out;
	//返回转换字节数的数量,但是转GBK时经常不正确 >=0就成功
	size_t re = iconv(cd, pin, &inlen, pout, &outlen);
	iconv_close(cd);
	return re;
}
#endif


	std::string LXData::GBKToUTF8()
	{
		string re = "";
#ifdef _WIN32	
		//GBK转unicode
		//1.1 统计转换后字节数
		int len = MultiByteToWideChar(CP_ACP,	//转换的格式
			0,			//默认的转换方式
			data,		//输入的字节
			-1,			//输入的字符串大小 -1 找\0
			0,//输出
			0//输出的空间大小
		);
		if (len <= 0)
			return re;
		wstring udata;//获取的字符串用udata存储
		udata.resize(len);//获取字符串的大小
		MultiByteToWideChar(CP_ACP, 0, data, -1, (wchar_t*)udata.data(), len);

		//2 unicode 转utf-8
		len = WideCharToMultiByte(CP_UTF8, 0, (wchar_t*)udata.data(), -1, 0, 0,
			0,	//失败默认替代字符,一但失败直接断掉了
			0	//是否使用默认替代 ,0代表false
		);
		if (len <= 0)
			return re;
		re.resize(len);
		WideCharToMultiByte(CP_UTF8, 0, (wchar_t*)udata.data(), -1, (char*)re.data(), len, 0, 0);
#else
		re.resize(1024);
		int inlen = strlen(data);
		Convert((char*)"gbk", (char*)"utf-8", (char*)data, inlen, (char*)re.data(), re.size());
		int outlen = strlen(re.data());
		re.resize(outlen);
#endif
		return re;
	}

utf-8转gbk

#ifndef _WIN32
static size_t Convert(char *from_cha, char *to_cha, char *in, size_t inlen, char *out, size_t outlen)
{
	//转换上下文
	iconv_t cd;
	cd = iconv_open(to_cha, from_cha);
	if (cd == 0)
		return -1;
	memset(out, 0, outlen);
	char **pin = &in;
	char **pout = &out;
	//返回转换字节数的数量,但是转GBK时经常不正确 >=0就成功
	size_t re = iconv(cd, pin, &inlen, pout, &outlen);
	iconv_close(cd);
	return re;
}
#endif


	std::string LXData::UTF8ToGBK()
	{
		string re = "";
		//1 UFT8 转为unicode win utf16
#ifdef _WIN32
	//1.1 统计转换后字节数
		int len = MultiByteToWideChar(CP_UTF8,	//转换的格式
			0,			//默认的转换方式
			data,		//输入的字节
			-1,			//输入的字符串大小 -1 找\0结束
			0,//输出
			0//输出的空间大小
		);
		if (len <= 0)
			return re;
		wstring udata;		//获取的字符串用udata存,这个出了作用域自动释放,不用自己释放
		udata.resize(len);	//获取的字符串用udata存
		MultiByteToWideChar(CP_UTF8, 0, data, -1, (wchar_t*)udata.data(), len);

		//2 unicode 转GBK
		len = WideCharToMultiByte(CP_ACP, 0, (wchar_t*)udata.data(), -1, 0, 0,
			0,	//失败默认替代字符
			0	//是否使用默认替代 
		);
		if (len <= 0)
			return re;
		re.resize(len);
		WideCharToMultiByte(CP_ACP, 0, (wchar_t*)udata.data(), -1, (char*)re.data(), len, 0, 0);
#else
		re.resize(1024);
		int inlen = strlen(data);
		Convert((char*)"utf-8", (char*)"gbk", (char*)data, inlen, (char*)re.data(), re.size());
		int outlen = strlen(re.data());
		re.resize(outlen);
#endif
		return re;
	}

3.LXMysql库添加字符集转换函数并测试GBK

  • 测试代码

4.简易获取数据的接口GetResult实现

5.mysql的表锁和行锁代码示例购票竞争

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值