iOS SQLite SELECT 使用 UTF 8 个字符
iOS SQLite SELECT with UTF 8 characters
我已经阅读了所有与 SQlite 编码相关的问题但没有成功,所以我会尝试询问我的具体情况。
我有一个预填充了 SQLite 数据库的 iOS 应用程序。
此 SQLite 已从 MySQL 数据库转换而来。
SQLite 和 MySQL 数据库都有 UTF8 编码(转换过程将默认的 sqlite 编码设置为 UTF8)
如果我用 Firefox SQlite Manager 打开我的 sqlite 数据库,我可以毫无问题地读取所有内容,并且所有 UTF8 字符都正确显示,所以我猜所有内容都已正确转换。
但是,当我尝试执行包含 UTF8 字符的 select 时,查询失败。
这是我执行查询的方法:
- (NSArray *)performQuery:(NSString *)query
{
static sqlite3 *db;
sqlite3_stmt *resultado;
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *writableDBPath = [documentsDirectory stringByAppendingPathComponent:@"mydatabase.sqlite"];
const char *dbpath = [writableDBPath UTF8String];
if (sqlite3_open(dbpath, &db) == SQLITE_OK)
{
printf("%s\n", [query UTF8String]);
int codigo = sqlite3_prepare_v2(db,[query UTF8String],[query length],&resultado,NULL);
if (codigo == SQLITE_OK)
{
NSMutableArray *result = [NSMutableArray array];
while (sqlite3_step(resultado) == SQLITE_ROW)
{
NSMutableArray *row = [NSMutableArray array];
for (int i = 0; i < sqlite3_column_count(resultado); i++)
{
int colType = sqlite3_column_type(resultado, i);
id value;
if (colType == SQLITE_TEXT)
{
value = [[NSString alloc] initWithUTF8String:(const char *) sqlite3_column_text(resultado, i)];
if ([value isEqualToString:@"(null)"] || [value isEqualToString:@""] || (value == nil) || [value isKindOfClass:[NSNull class]])
{
value = @"";
}
}
else if (colType == SQLITE_INTEGER)
{
int col = sqlite3_column_int(resultado, i);
value = [NSNumber numberWithInt:col];
}
else if (colType == SQLITE_FLOAT)
{
double col = sqlite3_column_double(resultado, i);
value = [NSNumber numberWithDouble:col];
}
else if (colType == SQLITE_NULL)
{
value = [NSNull null];
}
else
{
NSLog(@"ERROR: DataBase - performQuery - Campo desconocido");
}
[row addObject:value];
}
[result addObject:row];
row = nil;
}
sqlite3_finalize(resultado);
sqlite3_close(db);
resultado = nil;
return result;
}
else
{
NSLog(@"ERROR [%d](%s): %@", codigo, sqlite3_errmsg(db), query);
}
}
else
{
NSLog(@"ERROR: No se pudo abrir la base de datos");
}
sqlite3_close(db);
db = nil;
resultado = nil;
return nil;
}
这是我调用 performQuery 的方法:
- (int) getIdForItem:(NSString *)item
{
NSString *query = [NSString stringWithFormat:@"SELECT item_id FROM table_items WHERE item_name=\"%@\"", item];
NSLog(@"QUERY:\n%@", query);
NSArray *answer = [self performQuery:query];
if([answer count] > 0)
return [[[answer objectAtIndex:0] objectAtIndex:0] intValue];
return -1;
}
如果我打这个电话:
[self getIdForItem:@"Camión"];
这是输出:
QUERY:
SELECT item_id FROM table_items WHERE item_name="Camión"
SELECT item_id FROM table_items WHERE item_name="Camión"
ERROR [1](unrecognized token: ""Cami√≥n"): SELECT item_id FROM table_items WHERE item_name="Camión"
这个错误是在方法中产生的:
sqlite3_prepare_v2(db,[query UTF8String],[query length],&resultado,NULL)
那么,为什么在sqlite_prepare_v2中Camión被解读为Cami√≥n呢?查询和 sqlite 数据库都使用 UTF8,所以我想我遗漏了一些东西...
嗯,rmaddy 的解决方案非常适合我。我所做的是:
PerformQuery 几乎相同,它接收一个新参数:
- (NSArray *)performQuery:(NSString *)query withArgument:(NSString *)arg
就在 sqlite3_prepare_v2 之后,我进行了绑定:
int codigo = sqlite3_prepare_v2(db,[query UTF8String],[query length],&resultado,NULL);
if (codigo == SQLITE_OK)
{
sqlite3_bind_text(resultado, 1, [arg UTF8String], -1, SQLITE_TRANSIENT);
NSMutableArray *result = [NSMutableArray array];
while (sqlite3_step(resultado) == SQLITE_ROW)
最后,我这样调用这个方法:
- (int) getIdForItem:(NSString *)item
{
NSString *query = @"SELECT item_id FROM table_items WHERE item_name=?1";
NSLog(@"QUERY:\n%@", query);
NSArray *answer = [self performQuery:query];
if([answer count] > 0)
return [[[answer objectAtIndex:0] objectAtIndex:0] intValue];
return -1;
}
我已经阅读了所有与 SQlite 编码相关的问题但没有成功,所以我会尝试询问我的具体情况。
我有一个预填充了 SQLite 数据库的 iOS 应用程序。 此 SQLite 已从 MySQL 数据库转换而来。 SQLite 和 MySQL 数据库都有 UTF8 编码(转换过程将默认的 sqlite 编码设置为 UTF8)
如果我用 Firefox SQlite Manager 打开我的 sqlite 数据库,我可以毫无问题地读取所有内容,并且所有 UTF8 字符都正确显示,所以我猜所有内容都已正确转换。
但是,当我尝试执行包含 UTF8 字符的 select 时,查询失败。
这是我执行查询的方法:
- (NSArray *)performQuery:(NSString *)query
{
static sqlite3 *db;
sqlite3_stmt *resultado;
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *writableDBPath = [documentsDirectory stringByAppendingPathComponent:@"mydatabase.sqlite"];
const char *dbpath = [writableDBPath UTF8String];
if (sqlite3_open(dbpath, &db) == SQLITE_OK)
{
printf("%s\n", [query UTF8String]);
int codigo = sqlite3_prepare_v2(db,[query UTF8String],[query length],&resultado,NULL);
if (codigo == SQLITE_OK)
{
NSMutableArray *result = [NSMutableArray array];
while (sqlite3_step(resultado) == SQLITE_ROW)
{
NSMutableArray *row = [NSMutableArray array];
for (int i = 0; i < sqlite3_column_count(resultado); i++)
{
int colType = sqlite3_column_type(resultado, i);
id value;
if (colType == SQLITE_TEXT)
{
value = [[NSString alloc] initWithUTF8String:(const char *) sqlite3_column_text(resultado, i)];
if ([value isEqualToString:@"(null)"] || [value isEqualToString:@""] || (value == nil) || [value isKindOfClass:[NSNull class]])
{
value = @"";
}
}
else if (colType == SQLITE_INTEGER)
{
int col = sqlite3_column_int(resultado, i);
value = [NSNumber numberWithInt:col];
}
else if (colType == SQLITE_FLOAT)
{
double col = sqlite3_column_double(resultado, i);
value = [NSNumber numberWithDouble:col];
}
else if (colType == SQLITE_NULL)
{
value = [NSNull null];
}
else
{
NSLog(@"ERROR: DataBase - performQuery - Campo desconocido");
}
[row addObject:value];
}
[result addObject:row];
row = nil;
}
sqlite3_finalize(resultado);
sqlite3_close(db);
resultado = nil;
return result;
}
else
{
NSLog(@"ERROR [%d](%s): %@", codigo, sqlite3_errmsg(db), query);
}
}
else
{
NSLog(@"ERROR: No se pudo abrir la base de datos");
}
sqlite3_close(db);
db = nil;
resultado = nil;
return nil;
}
这是我调用 performQuery 的方法:
- (int) getIdForItem:(NSString *)item
{
NSString *query = [NSString stringWithFormat:@"SELECT item_id FROM table_items WHERE item_name=\"%@\"", item];
NSLog(@"QUERY:\n%@", query);
NSArray *answer = [self performQuery:query];
if([answer count] > 0)
return [[[answer objectAtIndex:0] objectAtIndex:0] intValue];
return -1;
}
如果我打这个电话:
[self getIdForItem:@"Camión"];
这是输出:
QUERY:
SELECT item_id FROM table_items WHERE item_name="Camión"
SELECT item_id FROM table_items WHERE item_name="Camión"
ERROR [1](unrecognized token: ""Cami√≥n"): SELECT item_id FROM table_items WHERE item_name="Camión"
这个错误是在方法中产生的:
sqlite3_prepare_v2(db,[query UTF8String],[query length],&resultado,NULL)
那么,为什么在sqlite_prepare_v2中Camión被解读为Cami√≥n呢?查询和 sqlite 数据库都使用 UTF8,所以我想我遗漏了一些东西...
嗯,rmaddy 的解决方案非常适合我。我所做的是:
PerformQuery 几乎相同,它接收一个新参数:
- (NSArray *)performQuery:(NSString *)query withArgument:(NSString *)arg
就在 sqlite3_prepare_v2 之后,我进行了绑定:
int codigo = sqlite3_prepare_v2(db,[query UTF8String],[query length],&resultado,NULL);
if (codigo == SQLITE_OK)
{
sqlite3_bind_text(resultado, 1, [arg UTF8String], -1, SQLITE_TRANSIENT);
NSMutableArray *result = [NSMutableArray array];
while (sqlite3_step(resultado) == SQLITE_ROW)
最后,我这样调用这个方法:
- (int) getIdForItem:(NSString *)item
{
NSString *query = @"SELECT item_id FROM table_items WHERE item_name=?1";
NSLog(@"QUERY:\n%@", query);
NSArray *answer = [self performQuery:query];
if([answer count] > 0)
return [[[answer objectAtIndex:0] objectAtIndex:0] intValue];
return -1;
}