2010-07-23 6 views
6

Finora sono riuscito a creare questo metodo per inserire in un database SQLite su iPhone:Inserimento NSData in SQLite su 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); 
} 

Ora sto guardando la memorizzazione di un'immagine nel database. Finora ho found this:

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

ma sto avendo problemi cercando di inserire questo NSData in array di caratteri che rende lo SQLStatement. Qualcuno ha un'idea di come farlo?

(Ho un campo nel database di tipo blob per questo).

Grazie

+1

Do * not * inserisce BLOB nel database. È orribilmente inefficiente a tutti i livelli. Archiviare un percorso nel database e inserire il BLOB nel filesystem. – bbum

+0

Vorrei * altamente * consigliare l'uso del wrapper del database Flying Meat, che ha già risolto tutti questi problemi per voi ed è * molto * più semplice da usare: http://github.com/ccgus/fmdb –

risposta

9

avrei usato sqlite3_stmt invece di una stringa. Quindi, è possibile utilizzare sqlite3_bind_blob per associare il BLOB all'istruzione preparata.

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); 

Ma, in realtà, sarebbe meglio per le prestazioni per memorizzare l'immagine sul disco e il percorso nel database.

Un altro modo per farlo, uno che utilizzo per inviare dati di immagine in XML, è quello di codificare 64 in base ai dati. Ce l'ho qui come categoria su 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 per sqlite3_stmt e per il salvataggio del file su disco invece che nel database –

+0

Grazie, non potrò provarlo fino a lunedì ma segnalerò. Per quanto riguarda il salvataggio su disco, questo è ciò che ho fatto in passato, ma ora sto trasmettendo in streaming e salvando le immagini. Non pensavo che si potesse salvare un'immagine su disco nel codice? –

+0

Oh, certo che puoi. Hai NSData: '[dataForImage writeToFile: path atomically: YES];' Crea un nome file univoco per la tua immagine e salvalo nella directory dei documenti. Quindi salvare quel percorso nel database. Per qualcosa di oltre 100 kb o giù di lì, è molto meglio di memorizzare il BLOB in sqlite. – Don