【问题标题】:sqlite3 insert and read BLOB data in databasesqlite3 在数据库中插入和读取 BLOB 数据
【发布时间】:2011-05-12 01:24:43
【问题描述】:

我需要在数据库中读取和写入 BLOB 数据。这是我的结构表

    #define CREATE_TABLE_USERS_SQL "CREATE TABLE IF NOT EXISTS %@ ( \
UserID INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, \
Name VARCHAR(50), \
Image BLOB);"

如何将其插入数据库,然后从中检索?

环境:iPhone SDK 4.1 SQLite3 数据库。

此代码失败:

        NSData * buf2 = [[NSData alloc] init];
        sqlite3_column_blob(statement, 5);
        buf2 = sqlite3_column_bytes(statement, 5);
        user.image = [UIImage imageWithData: buf2];

【问题讨论】:

标签: select insert sqlite blob


【解决方案1】:

谢谢大家!!在您的帮助下,我已经解决了问题,并希望为像我这样的未来初学者分享结果。)

-(void) addToDB
{
    NSLog(@"\nCreating db");
    NSString *str = @"CREATE TABLE IF NOT EXISTS Images (image1 BLOB);";
    int res = SQLITE_ERROR;


    res = sqlite3_open([@"aa.sql" UTF8String], &database);
    res = sqlite3_exec(database, [str UTF8String], NULL, NULL, NULL);

    sqlite3_stmt *updStmt =nil; 

    const char *sql = "INSERT INTO Images (image1) VALUES (?);";
    res = sqlite3_prepare_v2(database, sql, -1, &updStmt, NULL);

    if(res!= SQLITE_OK)
    {
        NSLog(@"Error while creating update statement:%s", sqlite3_errmsg(database));
    }

    UIImage *img = [UIImage imageNamed: @"flower.png"];
    NSData *imageData = [NSData dataWithData: UIImagePNGRepresentation(img)];

    res = sqlite3_bind_blob(updStmt, 1, [imageData bytes], [imageData length] , SQLITE_TRANSIENT);

    if((res = sqlite3_step(updStmt)) != SQLITE_DONE)
    {
        NSLog(@"Error while updating: %@", sqlite3_errmsg(database));
        sqlite3_reset(updStmt);
    } 

    res = sqlite3_reset(updStmt);
    res = sqlite3_close(database);
}

-(void) readFromDB
{
    NSLog(@"\nReading from db");

    NSString *query = @"SELECT image1 from Images";
    int res = SQLITE_ERROR;
    int len = 0;

    res = sqlite3_open([@"aa.sql" UTF8String], &database);

    sqlite3_stmt *statement;
    res = sqlite3_prepare_v2 (database, [query UTF8String], -1, &statement, nil);

    if (res == SQLITE_OK)
    {
        if (sqlite3_step(statement) == SQLITE_ROW)
        {
            len = sqlite3_column_bytes(statement, 0);
            NSData *imgData = [[NSData alloc] initWithBytes: sqlite3_column_blob(statement, 0) length: len];           


            UIImage *img = [[UIImage alloc] initWithData:imgData];

            self.view1.image = img;

        }
    }
    sqlite3_finalize(statement);

    res = sqlite3_close(database);
}

【讨论】:

  • 感谢发布,此代码运行良好。但是当我将图像名称从“flower.png”更改为“xyz.png”等其他名称时,它会在 imageview 中显示上一个图像你能指出原因吗.......
  • 可能你需要先到数据库中的相应记录,然后才从中读取图像,现在它总是取第一条记录。试试看,我真的不记得是一年前了。
  • in NSLog(@"创建更新语句时出错:%@", sqlite3_errmsg(database));应使用 %s 格式
  • 常量 SQLITE_BLOB 在 sqlite3_bind_blob 调用中被错误地使用。应该在那里使用 SQLITE_TRANSIENT 或 SQLITE_STATIC。 sqlite.org/c3ref/bind_blob.html
  • 小心使用 SQLITE_TRANSIENT 用法。根据您的情况,它可能会导致 BAD_ACCESS 错误。这是我的情况,直到我将其更改为 SQLITE_STATIC。
【解决方案2】:

除了选择您的客户端或编程接口外,用法与任何其他字符串字段没有区别。


[更新] 我还没有幸运地为 iPhone 开发,但我相信它与任何其他 SELECT 或 INSERT 查询相同。确保对 BLOB 进行编码并用单个撇号 (') 将其括起来,例如字符串。

【讨论】:

    【解决方案3】:

    为什么不用 fmdb fmdb 由 Gus Mueller et al,Flying Meat? http://flyingmeat.com/

    https://github.com/ccgus/fmdb

    如果你觉得fmdb 有用,就去买飞肉的优秀应用之一吧。 VoodooPad 或 Acron。

    【讨论】:

      【解决方案4】:

      //-----插入图片

        - (void)setImage:(UIImage *)theImage
       {
      
        if(sqlite3_open([databasePath UTF8String],&myDatabase)==SQLITE_OK)
        {    
          NSString *insertProgrammeSql = @"INSERT INTO imageTable (imageName) VALUES (?)";
      
      sqlite3_stmt *statement;
      
         if (sqlite3_prepare_v2(myDatabase, [insertProgrammeSql cStringUsingEncoding:NSUTF8StringEncoding], -1, &statement, NULL) == SQLITE_OK) {
      
          NSData *imageData = UIImagePNGRepresentation(theImage);
      
               sqlite3_bind_blob(statement, 1, [imageData bytes], [imageData length], SQLITE_TRANSIENT);
      
          sqlite3_step(statement);
      }
        sqlite3_close(myDatabase);
      //  return YES;    
      }   
      
      
        }
      

      //--------获取图片

         -(UIImage *)getImage
      
          {
      
          UIImage *image = nil;
      
      
      if(sqlite3_open([databasePath UTF8String],&myDatabase)==SQLITE_OK)
      {   
      
      NSString *selectSql = @"SELECT image FROM imageTable";
      
      sqlite3_stmt *statement;
      if (sqlite3_prepare_v2(myDatabase, [selectSql UTF8String], -1, &statement, NULL) == SQLITE_OK)
      {
          int length = sqlite3_column_bytes(statement, 0);
          NSData *imageData = [NSData dataWithBytes:sqlite3_column_blob(statement, 0 ) length:length];
      
          image = [UIImage imageWithData:imageData];
      
      
      
        sqlite3_finalize(statement);
      
        }
           sqlite3_close(myDatabase);
        }
       return image;
       }
      

      【讨论】:

        【解决方案5】:

        此代码失败:

           NSData * buf2 = [[NSData alloc] init];
           sqlite3_column_blob(statement, 5);
           buf2 = sqlite3_column_bytes(statement, 5);
           user.image = [UIImage imageWithData: buf2];
        

        您正在以正确的顺序调用 SQLite 函数。根据 SQLite 文档:

        最安全、最容易记住的策略是调用这些例程 通过以下方式之一:

        • sqlite3_column_text() 后跟 sqlite3_column_bytes()
        • sqlite3_column_blob() 后跟 sqlite3_column_bytes()
        • sqlite3_column_text16() 后跟 sqlite3_column_bytes16()

        换句话说,你应该调用 sqlite3_column_text(), sqlite3_column_blob() 或 sqlite3_column_text16() 首先强制 结果转换为所需的格式,然后调用 sqlite3_column_bytes() 或 sqlite3_column_bytes16() 来查找结果的大小。不要混在一起 调用 sqlite3_column_text() 或 sqlite3_column_blob() 并调用 sqlite3_column_bytes16(),并且不要混合调用 sqlite3_column_text16() 调用 sqlite3_column_bytes()。

        但是,buff2 是一个整数,而不是数据指针。 sqlite3_column_bytes 告诉您 blob 中有多少字节。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2011-12-21
          • 2012-07-11
          • 1970-01-01
          • 2021-03-03
          • 1970-01-01
          • 2017-07-17
          • 2013-10-06
          • 1970-01-01
          相关资源
          最近更新 更多