MFC操作打开SqLite数据库,其中szDBFile为数据库所在的位置。最开始使用的相对路径,即szDBFile永远等于“HData.zip”。但是尤其设备需要,需要把.exe文件放入开机启动的shell中。这样使用相对路径就会产生错误,即需要给szDBFile赋值绝对路径。此时,如果全路径包括汉字,那样sqlite3_open_v2(szDBFile, &m_sq3DB, SQLITE_OPEN_READWRITE, NULL)不会成功。代码如下:
if (SQLITE_OK != sqlite3_open_v2(szDBFile, &m_sq3DB, SQLITE_OPEN_READWRITE, NULL))
{ //创建新的数据库
sqlite3_open_v2(szDBFile, &m_sq3DB, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, NULL);
sqlite3_exec(m_sq3DB, SQL_NEWDB, NULL, NULL, NULL);
}
原因分析:SqLite只支持UTF-8编码,所以无法识别包含汉字的多字符集。因此,需要将全路径名称由多字符集转换为Unicode字符集,再由Unicode字符集转换为UTF-8编码格式。转换函数如下:
//有多字符集转换为Unicode
WCHAR *CDB::mbcsToUnicode(const char *zFilename)
{
int nByte;
WCHAR *zMbcsFilename;
int codepage = AreFileApisANSI() ? CP_ACP : CP_OEMCP;
nByte = MultiByteToWideChar(codepage, 0, zFilename, -1, NULL,0)*sizeof(WCHAR);
zMbcsFilename = (WCHAR *)malloc(nByte*sizeof(zMbcsFilename[0]));
if( zMbcsFilename==0 )
{
return 0;
}
nByte = MultiByteToWideChar(codepage, 0, zFilename, -1, zMbcsFilename, nByte);
if(nByte == 0)
{
free(zMbcsFilename);
zMbcsFilename = 0;
}
return zMbcsFilename;
}
//有Unicode转为UTF-8
char *CDB::unicodeToUtf8(const WCHAR *zWideFilename)
{
int nByte; char *zFilename;
nByte = WideCharToMultiByte(CP_UTF8, 0, zWideFilename, -1, 0, 0, 0, 0);
zFilename = (char *)malloc(nByte);
if(zFilename == 0)
{
return 0;
}
nByte = WideCharToMultiByte(CP_UTF8, 0, zWideFilename, -1, zFilename, nByte, 0, 0);
if( nByte == 0 )
{
free(zFilename);
zFilename = 0;
}
return zFilename;
}
最后使用代码:
char * pPath;
WCHAR *wcPath;
wcPath = mbcsToUnicode(strFullPath);//strFulPath即为带有中文的全路径字符串
pPath = unicodeToUtf8(wcPath );
szDBFile = pPath;
if (SQLITE_OK != sqlite3_open_v2(szDBFile, &m_sq3DB, SQLITE_OPEN_READWRITE, NULL))
{ //创建新的数据库
sqlite3_open_v2(szDBFile, &m_sq3DB, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, NULL);
sqlite3_exec(m_sq3DB, SQL_NEWDB, NULL, NULL, NULL);
}