2010-07-23 4 views
6

До сих пор мне удалось создать этот метод для вставки в базу данных SQLite на iPhone:Вставка NSData в SQLite на iPhone

- (void) insertToDB :(NSString *)Identifier :(NSString *)Name 
{ 
    sqlite3 *database; 

    if(sqlite3_open([databasePath UTF8String], &database) == SQLITE_OK) 
    { 
     char *sql1 = "INSERT INTO table VALUES ('"; 
     const char *sql2 = [Identifier cStringUsingEncoding:[NSString defaultCStringEncoding]]; 
     char *sql3 = "', '"; 
     const char *sql4 = [Name cStringUsingEncoding:[NSString defaultCStringEncoding]]; 
     char *sql5 = "')"; 

     char *sqlStatement[255]; 
     strcpy(sqlStatement, sql1); 
     strcat(sqlStatement, sql2); 
     strcat(sqlStatement, sql3); 
     strcat(sqlStatement, sql4); 
     strcat(sqlStatement, sql5); 

     sqlite3_stmt *compiledStatement; 

     if(sqlite3_prepare_v2(database, sqlStatement, -1, &compiledStatement, NULL) == SQLITE_OK) 
     { 
      sqlite3_last_insert_rowid(database); 
      sqlite3_reset(compiledStatement); 
     } 

     sqlite3_finalize(compiledStatment); 
    } 
    sqlite3_close(database); 
} 

Теперь я смотрю на хранение изображений в базе данных. До сих пор я found this:

UIImage *cachedImage = [UIImage imageNamed:@"Icon.png"]; 
NSData *dataForImage = UIImagePNGRepresentation(cachedImage); 

Но у меня возникают проблемы при попытке вставить этот NSData в массив символов, который делает SQLStatement. Кто-нибудь понял, как это сделать?

(У меня есть поле в базе данных типа blob для этого).

Благодаря

+1

Do * not * put BLOBs в базе данных. Это ужасно неэффективно на всех уровнях. Сохраните путь в базе данных и поместите BLOB в файловую систему. – bbum

+0

Я бы * очень * рекомендую использовать обертку базы данных Flying Meat, которая уже решила все эти проблемы и * очень проста в использовании: http://github.com/ccgus/fmdb –

ответ

9

Я хотел бы использовать sqlite3_stmt вместо строки. Затем вы можете использовать sqlite3_bind_blob, чтобы привязать blob к подготовленному оператору.

sqlite3_stmt *insert_statement;  
char *sql = "INSERT INTO table (blobcolumn, column2, column3) VALUES (? , ?, ?)" ; 
if(sqlite3_prepare_v2(database, sql, -1, &insert_statement, NULL) != SQLITE_OK) 
      { 
       //handle error 
      } 

sqlite3_bind_blob(insert_statement, 1, [dataForImage bytes], [dataForImage length], NULL); 

Но, действительно, лучше было бы сохранить изображение на диске и путь в базе данных.

Другой способ сделать это, тот, который я использую для отправки данных изображения в XML, заключается в кодировании данных на базе 64. У меня есть здесь как категория на NSString:

static char base64EncodingTable[64] = { 
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 
'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 
'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 
'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/' 
}; 

@implementation NSString (NSStringCategories) 

+ (NSString *) base64StringFromData: (NSData *)data length: (int)length { 
    unsigned long ixtext, lentext; 
    long ctremaining; 
    unsigned char input[3], output[4]; 
    short i, charsonline = 0, ctcopy; 
    const unsigned char *raw; 
    NSMutableString *result; 

    lentext = [data length]; 
    if (lentext < 1) 
     return @""; 
    result = [NSMutableString stringWithCapacity: lentext]; 
    raw = [data bytes]; 
    ixtext = 0; 

    while (true) { 
     ctremaining = lentext - ixtext; 
     if (ctremaining <= 0) 
      break;   
     for (i = 0; i < 3; i++) { 
      unsigned long ix = ixtext + i; 
      if (ix < lentext) 
       input[i] = raw[ix]; 
      else 
       input[i] = 0; 
     } 
     output[0] = (input[0] & 0xFC) >> 2; 
     output[1] = ((input[0] & 0x03) << 4) | ((input[1] & 0xF0) >> 4); 
     output[2] = ((input[1] & 0x0F) << 2) | ((input[2] & 0xC0) >> 6); 
     output[3] = input[2] & 0x3F; 
     ctcopy = 4; 
     switch (ctremaining) { 
      case 1: 
       ctcopy = 2; 
       break; 
      case 2: 
       ctcopy = 3; 
       break; 
    } 

    for (i = 0; i < ctcopy; i++) 
     [result appendString: [NSString stringWithFormat: @"%c",    base64EncodingTable[output[i]]]]; 

    for (i = ctcopy; i < 4; i++) 
     [result appendString: @"="]; 

    ixtext += 3; 
    charsonline += 4; 

    if ((length > 0) && (charsonline >= length)) 
     charsonline = 0; 
    } 
    return result; 
} 
+1

+1 для sqlite3_stmt и для сохранения файла на диск, а не в базе данных –

+0

Спасибо, я не смогу попробовать это до понедельника, но я отчитаюсь. Что касается сохранения на диск, это то, что я делал в прошлом, но теперь я передаю и сохраняю изображения. Я не думал, что вы можете сохранить изображение на диск в коде? –

+0

О, конечно, вы можете. У вас есть NSData: '[dataForImage writeToFile: путь атомарно: ДА];' Создайте уникальное имя файла для вашего изображения и сохраните его в каталоге документов. Затем сохраните этот путь в базе данных. Для чего-либо более 100 кб или около того, это намного лучше, чем хранение BLOB в sqlite. – Don

Смежные вопросы