关于MFC中ANSI与UNICODE编码的问题(涉及数据库)

NeetSonic 2015-08-23 12:38:29
我采用SQLITE3作为数据库,但是往SQLITE3里面写入数据好像必须是ANSI编码(SQLITE的API要求的)。
然而MFC工程中一般使用Unicode编码与控件交互信息,经过在网上各处搜索,最后得出的这个方法进行相互转换:
static void UnicodeToAnsi(const wchar_t* srcStr, char* destStr, const UINT & nMaxBytesToConvert) {
int nLen = WideCharToMultiByte(CP_ACP, 0, srcStr, -1, NULL, 0, NULL, NULL);
if(nLen) {
char* p = new char[nLen];
WideCharToMultiByte(CP_ACP, 0, srcStr, -1, p, nLen, NULL, NULL);
strcpy_s(destStr, nMaxBytesToConvert, p);
MultiDelete(p);
}
}
static void AnsiToUnicode(const char* srcStr, wchar_t* destStr, const UINT & nMaxBytesToConvert) {
int nLen = MultiByteToWideChar(CP_ACP, 0, srcStr, -1, NULL, 0);
if(nLen) {
wchar_t * pUnicode = new wchar_t[nLen];
MultiByteToWideChar(CP_ACP, 0, srcStr, -1, pUnicode, nLen);
wcscpy_s(destStr, nMaxBytesToConvert, pUnicode);
MultiDelete(pUnicode);
}
}


使用这个方法,对大部分的字符都可以正常存储。
然而,对于这个点号我却没辙“・”(注意这个点号,并不是句号,位置比句号高,一般用于人名,比如 爱德华・G・维克多)
对这个点使用上述方法,转换ANSI后就变成了问号"?"了。

测试代码如下:
	wchar_t *p = L"・";
MessageBox(p);

char buf[10];
memset(buf, 0, 10);
UnicodeToAnsi(p, buf, 10);

CString cs(buf);
MessageBox(cs);

wchar_t buf2[10];
memset(buf2, 0, 20);
AnsiToUnicode(buf, buf2, 10);
MessageBox(buf2);


结果分别是:




可见这个符号"・",用UNICODE编码的方式可以存储,但是转换ANSI后,就不能转回来了,不知道有什么办法可以解决呢?
希望能顺便了解到一些关于编码的知识, 先谢谢了。

...全文
397 29 打赏 收藏 转发到动态 举报
写回复
用AI写文章
29 条回复
切换为时间正序
请发表友善的回复…
发表回复
sdytdhl 2015-08-25
  • 打赏
  • 举报
回复
骚年,sqlite是utf8,不是ansi的
zwfgdlc 2015-08-24
  • 打赏
  • 举报
回复
要用sqlite3_open16打开数据库,
wchar_t *sql = L"INSERT INTO Producer VALUES(NULL, '爱德华・维克多')"
直接单引号就行,
NeetSonic 2015-08-24
  • 打赏
  • 举报
回复
引用 19 楼 schlafenhamster 的回复:
请使用 afxDump.HexDump("0x", (BYTE*)MiddleDotW, 2, 2); 取那个点的 Uncode 编码 可以使用 Replace 替换 为 0x00B7 来显示
嗯,这也是最后没有办法了才采用替换的方式
NeetSonic 2015-08-24
  • 打赏
  • 举报
回复
引用 18 楼 zwfgdlc 的回复:
要用sqlite3_open16打开数据库,
wchar_t *sql = L"INSERT INTO Producer VALUES(NULL, '爱德华・维克多')"
直接单引号就行,
	int ret;
	ret = sqlite3_open16("./db/anime.db", &db);
	if(ret != SQLITE_OK) {
		MessageBox(L"Access Failed!");
		return TRUE;
	}
	wchar_t *sql = L"INSERT INTO Producer VALUES(NULL, '爱德华・维克多')";
	sqlite3_stmt *stmt;
	const void *tail = NULL;
	if(sqlite3_prepare16(db, sql, wcslen(sql) * 2, &stmt, &tail) != SQLITE_OK) {
		MessageBox(L"Error");
	}
	else {
		sqlite3_step(stmt);
	}
sqlite3_open16没有报错,但是sqlite3_prepare16报错了,我不知道怎么查看错误信息
schlafenhamster 2015-08-24
  • 打赏
  • 举报
回复
请使用 afxDump.HexDump("0x", (BYTE*)MiddleDotW, 2, 2); 取那个点的 Uncode 编码 可以使用 Replace 替换 为 0x00B7 来显示
sumos 2015-08-24
  • 打赏
  • 举报
回复
sqlite用的好像是UTF8吧???
NeetSonic 2015-08-24
  • 打赏
  • 举报
回复
引用 26 楼 zwfgdlc 的回复:
你得用sqlite3_column_text16()不是用sqlite3_column_text()
唉,承认自己确实对SQLITE不熟,操作起来确实有点累,最后还是妥协了,采用ADO操作ACCESS算了。 不过还是很感谢你讲了那么多,我这个项目比较急,不然就去sqlite官方网站多看看文档了。
zwfgdlc 2015-08-24
  • 打赏
  • 举报
回复

你得用sqlite3_column_text16()不是用sqlite3_column_text()
schlafenhamster 2015-08-24
  • 打赏
  • 举报
回复
你那个点 是 unicode 0x0700 (比较粗)而不是 0xB700 !
NeetSonic 2015-08-24
  • 打赏
  • 举报
回复
引用 23 楼 NeetSonic 的回复:
[quote=引用 22 楼 zwfgdlc 的回复:]
const WCHAR* errorstr = (LPWSTR)sqlite3_errmsg16(db);
看下出错信息. 还有你的Producer表是怎么样的,储存'爱德华・维克多'的字段是什么类型?
ID INTEGER AUTOINCREMENT PRIMARY KEY; NAME TEXT NOT NULL UNIQUE[/quote] 报错的问题在于sqlite3_open16的参数应该用wchar_t的字符串,我用的char,所以他没找到数据库。 然而我改成wchar_t的字符串后,数据库找到了,执行代码后插入进去还是乱码。。。醉了
NeetSonic 2015-08-24
  • 打赏
  • 举报
回复
引用 22 楼 zwfgdlc 的回复:
const WCHAR* errorstr = (LPWSTR)sqlite3_errmsg16(db);
看下出错信息. 还有你的Producer表是怎么样的,储存'爱德华・维克多'的字段是什么类型?
ID INTEGER AUTOINCREMENT PRIMARY KEY; NAME TEXT NOT NULL UNIQUE
zwfgdlc 2015-08-24
  • 打赏
  • 举报
回复
const WCHAR* errorstr = (LPWSTR)sqlite3_errmsg16(db);
看下出错信息. 还有你的Producer表是怎么样的,储存'爱德华・维克多'的字段是什么类型?
NeetSonic 2015-08-23
  • 打赏
  • 举报
回复
引用 15 楼 zwfgdlc 的回复:
[quote=引用 11 楼 NeetSonic 的回复:] [quote=引用 4 楼 zwfgdlc 的回复:] 那就不要用sqlite3_exec(),用sqlite3_prepare16(),sqlite3_step()
亲能否针对我的问题,给出一个好的例子呢, 我做了一下尝试:
	wchar_t *sql = L"INSERT INTO Producer VALUES(NULL, \"爱德华・维克多\")";
	sqlite3_stmt *stmt;
	const void *tail = NULL;
	if(sqlite3_prepare16_v2(db, sql, wcslen(sql) * 2, &stmt, &tail) == SQLITE_OK) {
		MessageBox(L"OK");
		sqlite3_step(stmt);
	}
然而查看数据库,发现存进去的内容变成了乱码。[/quote] 你下断点调试下,看内存数据,是不是UNICODE编码的汉字. 比如"爱德化"UNICODE编码等于0x3172,0xb75f, 0x4e53 [/quote] 这是问题必定出在sqlite3_prepare16_v2内部的,貌似不好调试。
NeetSonic 2015-08-23
  • 打赏
  • 举报
回复
引用 10 楼 zhusg 的回复:
你那个点在ANSI中是不存在的 所以会显示问号
哦,就是说使用SQLITE是没有办法存放这个字符的是吧。 有没有基于UNICODE编码存放数据的轻量级数据库推荐呢,我也不想吊死在SQLITE上。
引用 14 楼 zhusg 的回复:
\"爱德华・维克多\" 这里不要用双引号 要用单引号 这里sqlite3_prepare16_v2(db, sql, wcslen(sql) * 2, &stmt, &tail) 改成sqlite3_prepare16_v2(db, sql, -1, &stmt, 0)
单双引号没有影响的,即使换成单引号,再使用你说的代码,结果还是乱码。
zwfgdlc 2015-08-23
  • 打赏
  • 举报
回复
引用 11 楼 NeetSonic 的回复:
[quote=引用 4 楼 zwfgdlc 的回复:] 那就不要用sqlite3_exec(),用sqlite3_prepare16(),sqlite3_step()
亲能否针对我的问题,给出一个好的例子呢, 我做了一下尝试:
	wchar_t *sql = L"INSERT INTO Producer VALUES(NULL, \"爱德华・维克多\")";
	sqlite3_stmt *stmt;
	const void *tail = NULL;
	if(sqlite3_prepare16_v2(db, sql, wcslen(sql) * 2, &stmt, &tail) == SQLITE_OK) {
		MessageBox(L"OK");
		sqlite3_step(stmt);
	}
然而查看数据库,发现存进去的内容变成了乱码。[/quote] 你下断点调试下,看内存数据,是不是UNICODE编码的汉字. 比如"爱德化"UNICODE编码等于0x3172,0xb75f, 0x4e53
zhusg 2015-08-23
  • 打赏
  • 举报
回复
\"爱德华・维克多\" 这里不要用双引号 要用单引号 这里sqlite3_prepare16_v2(db, sql, wcslen(sql) * 2, &stmt, &tail) 改成sqlite3_prepare16_v2(db, sql, -1, &stmt, 0)
zhusg 2015-08-23
  • 打赏
  • 举报
回复
引用 12 楼 NeetSonic 的回复:
[quote=引用 10 楼 zhusg 的回复:] 你那个点在ANSI中是不存在的 所以会显示问号
哦,就是说使用SQLITE是没有办法存放这个字符的是吧。 有没有基于UNICODE编码存放数据的轻量级数据库推荐呢,我也不想吊死在SQLITE上。[/quote] access就可以
NeetSonic 2015-08-23
  • 打赏
  • 举报
回复
引用 10 楼 zhusg 的回复:
你那个点在ANSI中是不存在的 所以会显示问号
哦,就是说使用SQLITE是没有办法存放这个字符的是吧。 有没有基于UNICODE编码存放数据的轻量级数据库推荐呢,我也不想吊死在SQLITE上。
NeetSonic 2015-08-23
  • 打赏
  • 举报
回复
引用 4 楼 zwfgdlc 的回复:
那就不要用sqlite3_exec(),用sqlite3_prepare16(),sqlite3_step()
亲能否针对我的问题,给出一个好的例子呢, 我做了一下尝试:
	wchar_t *sql = L"INSERT INTO Producer VALUES(NULL, \"爱德华・维克多\")";
	sqlite3_stmt *stmt;
	const void *tail = NULL;
	if(sqlite3_prepare16_v2(db, sql, wcslen(sql) * 2, &stmt, &tail) == SQLITE_OK) {
		MessageBox(L"OK");
		sqlite3_step(stmt);
	}
然而查看数据库,发现存进去的内容变成了乱码。
zhusg 2015-08-23
  • 打赏
  • 举报
回复
你那个点在ANSI中是不存在的 所以会显示问号
加载更多回复(9)

4,011

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 数据库
社区管理员
  • 数据库
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧