简体   繁体   English

使用Sqlite3 C ++和VisualStudio2010在INSERT期间编码问题

[英]Encoding problems during INSERT with Sqlite3 C++ and VisualStudio2010

I'm developing a small wrapper for a project using sqlite3 with the C++ API and VisualStudio 2010. As far as it goes and checking with a tool like SQLiteDataBaseBrowser, the main problem is that the information I try to insert in the table appears corrupted / doesn't appear at all. 我正在使用sqlite3和C ++ API以及VisualStudio 2010为一个项目开发一个小包装器。就像使用SQLiteDataBaseBrowser这样的工具进行检查一样,主要问题是我尝试在表中插入的信息显示为损坏/根本没有出现。 The table appears to be correctly created with UTF8 encoding. 该表似乎是使用UTF8编码正确创建的。

I tried using the Character Set configuration values in VS as "Use Multy-Byte Character set" and also tried with "Use Unicode Character set" but got no change in the result. 我尝试将VS中的字符集配置值用作“使用多字节字符集”,并尝试使用“使用Unicode字符集”,但结果没有变化。 Both gave me the same problem with the corrupted data. 两者都给我带来了与损坏数据相同的问题。 I use the typical std::strings converted to legacy c char* and as I've seen in several examples that it should work properly with sqlite3_bind_text(...) functions that the API provides. 我使用典型的std :: strings转换为legacy c char *,正如我在几个例子中看到的,它应该与API提供的sqlite3_bind_text(...)函数一起正常工作。

    sqlite3_bind_int(stmt, 1, newShop.GetId());
    sqlite3_bind_text(stmt, 2, newShop.GetName().c_str(), -1, SQLITE_STATIC);
    sqlite3_bind_text(stmt, 3, newShop.GetLocation().c_str(), -1, SQLITE_STATIC);
    sqlite3_bind_text(stmt, 4, newShop.GetPicturePath().c_str(), -1, SQLITE_STATIC);
    sqlite3_bind_text(stmt, 5, newShop.GetRegisters().c_str(), -1, SQLITE_STATIC);
    sqlite3_bind_text(stmt, 6, newShop.GetMixes().c_str(), -1, SQLITE_STATIC);
    sqlite3_bind_text(stmt, 7, newShop.GetAllowedUsers().c_str(), -1, SQLITE_STATIC);
    sqlite3_bind_int(stmt, 8, newShop.IsAvailable() == true?1:0);

newShop is an instance of a class which contains the information in std::strings and int. newShop是一个类的实例,它包含std :: strings和int中的信息。 I have to say that the bindings with int type, work perfectly and without problem, but the others look totally messed up. 我不得不说使用int类型的绑定,工作完美且没有问题,但其他人看起来完全搞砸了。 when the strings are hardcoded, they also look ok until I try to insert special characters such as "áàä" and such. 当字符串被硬编码时,它们看起来还不错,直到我尝试插入特殊字符,如“áàä”等。

The table is created with the statement: 该表是使用以下语句创建的:

char *szSQL = "CREATE TABLE IF NOT EXISTS SHOPS (ID INTEGER PRIMARY KEY NOT NULL, NAME TEXT NOT NULL, LOCATION TEXT, PICTUREPATH TEXT, REGISTERS TEXT, MIXES TEXT, USERS TEXT, AVAILABLE INTEGER NOT NULL);";
int rc = sqlite3_exec(db, szSQL, NULL, 0, NULL);

This is how it looks when I insert the data using the code snippet above: 这是我使用上面的代码片段插入数据时的外观:

DataBase编码问题

sending it from a WINUNIT test that looks like: 从WINUNIT测试发送它看起来像:

Shop shOne = Shop(1234, "Its about nothing", "Manhattan", "seinfeld.jpg", "1111,2222,3333", "1000x1,2000x7", "10,11,12", true); 
Shop shTwo = Shop(4321, "Louie", "Manhattan", "", "1111,5555", "50000x1,10000x5", "60,70", true);

WIN_ASSERT_EQUAL(0, auxsql.InsertShop(shOne));
WIN_ASSERT_EQUAL(0, auxsql.InsertShop(shTwo));

Neither the insertion, the commit, the creation of the sql statement or any other function call to the sqlite3 API return an error code. 插入,提交,创建sql语句或对sqlite3 API的任何其他函数调用都不会返回错误代码。

I found the solution. 我找到了解决方案。 It was nothing related to encoding, as I thought because of the characters being strangely represented in the DB browser and also nothing related to the length. 它与编码无关,正如我想的那样,因为在DB浏览器中奇怪地表示了字符,而且与长度无关。

The problem was in the last parameter of the binding. 问题出在绑定的最后一个参数中。 Where i pass SQLITE_STATIC, I should have passed SQLITE_TRANSIENT, as the object returned by the calls I want to bind are possibly destructed before the query is executed. 在我传递SQLITE_STATIC的地方,我应该传递SQLITE_TRANSIENT,因为我想要绑定的调用返回的对象可能在执行查询之前被破坏。 Just as it is explained in this other question: 正如在另一个问题中解释的那样:

sqlite3_bind_text SQLITE_STATIC vs SQLITE_TRANSIENT for c++ string sqlite3_bind_text用于c ++字符串的SQLITE_STATIC与SQLITE_TRANSIENT

I think sqlite reference is quite clear about the API usage. 我认为sqlite引用非常清楚API的用法。

In those routines that have a fourth argument, its value is the number of bytes in the parameter. 在具有第四个参数的那些例程中,其值是参数中的字节数。 To be clear: the value is the number of bytes in the value, not the number of characters. 要清楚:值是值中的字节数,而不是字符数。

As per your usage, 根据您的使用情况,

sqlite3_bind_text(stmt, 2, newShop.GetName().c_str(), -1, SQLITE_STATIC); the 4th arguement is -1 . 第四个论点是-1 However it should be either newShop.GetName().length or strlen(newShop.GetName().c_str())` 但它应该是newShop.GetName().length或strlen(newShop.GetName()。c_str())`

Note : be careful when you deal with string with multi-wide chars. 注意:处理具有多宽字符的字符串时要小心。 Where strlen(chinese string) ! = chinese string.len strlen(chinese string) ! = chinese string.len strlen(chinese string) ! = chinese string.len . strlen(chinese string) ! = chinese string.len Refer here for more details. 请参阅此处了解更多详情。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM