【问题标题】:To retrieve BLOB image from sqlite从 sqlite 检索 BLOB 图像
【发布时间】:2012-04-28 21:27:07
【问题描述】:

图片保存代码:

NSData *imageData=UIImagePNGRepresentation(animalImage);
        NSString *insertSQL=[NSString stringWithFormat:@"insert into AnimalsTable (name,propertyID,animalID,breed,mainBreed,dateofbirth,sex,notes,imageData) values(\"%@\",\"%@\",\"%@\",\"%@\",\"%@\",\"%@\",\"%@\",\"%@\",\"%@\")",nameString,propertyString,animalidString,breedString,mainBreedString,dateString,sexString,notesString,imageData];
    sqlite3_stmt *addStatement;
        NSLog(@"%@",appDelegate.sqlFile);
    const char *insert_stmt=[insertSQL UTF8String];
    if (sqlite3_open([appDelegate.sqlFile UTF8String],&database)==SQLITE_OK) {
        sqlite3_prepare_v2(database,insert_stmt,-1,&addStatement,NULL);

        if (sqlite3_step(addStatement)==SQLITE_DONE) {

            sqlite3_bind_blob(addStatement, 1, [imageData bytes], [imageData length], SQLITE_TRANSIENT);
            NSLog(@"Data saved");

        }
        else{
            //NSAssert1(0, @"Error while updating. '%s'", sqlite3_errmsg(database));

            NSLog(@"Some Error occured");
    }

    sqlite3_close(database);

用于检索图像:

NSString *select_sql=[NSString stringWithFormat:@"select name,animalID,imageData from AnimalsTable where mainBreed='%@' AND breed='%@'",mainString,subString];
        const char *sql = [select_sql UTF8String];
        sqlite3_stmt *selectstmt;
        if(sqlite3_prepare_v2(database, sql, -1, &selectstmt, NULL) == SQLITE_OK) {

            while(sqlite3_step(selectstmt) == SQLITE_ROW) {

            NSString *animalName = [NSString stringWithUTF8String:(char *)sqlite3_column_text(selectstmt, 0)];
            NSString *animalid=[NSString stringWithUTF8String:(char *)sqlite3_column_text(selectstmt, 1)];
            NSData *dataForCachedImage = [[NSData alloc] initWithBytes:sqlite3_column_blob(selectstmt, 2) length: sqlite3_column_bytes(selectstmt, 2)];           
            [animalNamesArray addObject:animalName];
            [animalIDArray addObject:animalid];
            [imageDataArray addObject:dataForCachedImage];

        }
    }
}
else
    sqlite3_close(database); 

在 UITableView CellForIndexPath 中:

NSData *dataForCachedImage=[imageDataArray objectAtIndex:indexPath.row];
    UIImage *dataImage=[[UIImage alloc] init];
    dataImage=[UIImage imageWithData:dataForCachedImage];
    cell.imageView.image=dataImage;

当我调试代码时:

我得到 NSData=226381 字节和 dataImage 0x0 的字节。

请帮帮我。

【问题讨论】:

  • 要开始你需要正确bind your values using ?。尝试使用 %@ 替换值就像 dangerous 与任何其他关系数据库一样。
  • 你能告诉我我上面的代码有什么问题,除了使用 %@ 而不是 ?.

标签: iphone objective-c sqlite blob


【解决方案1】:

您需要将您的值正确绑定到查询才能正常工作。当您在第一行设置查询时,将插入数据的描述,而不是正确的数据。如果您要记录查询,您可能会看到类似<0FFAEC32 ... 23F0E8D1> 的内容。 然后,您稍后尝试正确绑定 blob,但由于您的查询未正确写入,因此没有任何效果。

//Although you try to bind a blob here it does not get bound
//to anything since you do not include a parameter template.
sqlite3_bind_blob(addStatement, 1, [imageData bytes], [imageData length], SQLITE_TRANSIENT);

在这里解决这个问题是一个最小的例子:

//query does not need to be an NSString* but just a const char *
//replace all %@ with ?
const char *sql = "INSERT INTO AnimalsTable(name, ..., imageData) values(?, ..., ?)";
if (sqlite3_open([appDelegate.sqlFile UTF8String],&database)==SQLITE_OK) {
        sqlite3_prepare_v2(database,insert_stmt,-1,&addStatement,NULL);

        //Bind all of the values here before you execute the statement
        sqlite3_bind_text(addStatement, 1, [nameString UTF8String], -1, NULL);
        ...
        sqlite3_bind_blob(addStatement, 9, [imageData bytes], [imageData length], SQLITE_TRANSIENT);

        if (sqlite3_step(addStatement)==SQLITE_DONE) {
            NSLog(@"Data saved");
        }
        ...

        //You must finalize your statement before closing the database
        sqlite3_finalize(addStatement);
        sqlite3_close(database);

使用绑定值有助于防止插入可能是 SQL 注入攻击的无效数据,并提高经常运行的查询的查询性能。

注意*:如果您要执行大量 SQL,请考虑使用 FMDB 甚至 Core Data。

【讨论】:

  • 我也做了你提到的类似的事情,但是当我在 sql manager 中检查时,数据正在以空值保存。
  • 我改变了 sqlite3_bind_text(addStatement, 1, [nameString UTF8String], -1, NULL);到 SQLITE_TRANSIENT。现在数据正在正确保存。但原来的问题依然存在。
  • 我用过?在我的整个查询中标记并更改了位置。
  • 抱歉,我复制了您示例的结构,但没有检查逻辑。执行语句后,您还尝试绑定 blob。我会更新答案。
  • 没关系,你能更新你的答案吗,因为我的整个应用程序都依赖于检索图像。
猜你喜欢
  • 2015-11-21
  • 1970-01-01
  • 1970-01-01
  • 2023-03-03
  • 1970-01-01
  • 2013-09-29
  • 1970-01-01
  • 2019-11-24
  • 2011-09-09
相关资源
最近更新 更多