2010-07-23 11 views
6

Hasta ahora no hemos logrado crear este método para insertar en una base de datos SQLite en el iPhone:Inserción NSData en SQLite en el 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); 
} 

Ahora estoy mirando a almacenar una imagen en la base de datos. Hasta ahora he found this:

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

pero estoy teniendo problemas tratando de insertar este NSData en la matriz de caracteres que hace que el SqlStatement. Alguien tiene una idea de cómo hacer esto?

(Tengo un campo en la base de datos de tipo blob para esto).

Gracias

+1

No * ponga los BLOB en la base de datos. Es horriblemente ineficiente en todos los niveles. Almacene una ruta en la base de datos y coloque el BLOB en el sistema de archivos. – bbum

+0

Recomendaría * altamente utilizar la envoltura de la base de datos de Flying Meat, que ya ha resuelto todos estos problemas y es * mucho * más fácil de usar: http://github.com/ccgus/fmdb –

Respuesta

9

yo usaría sqlite3_stmt lugar de una cadena. Luego, podría usar sqlite3_bind_blob para vincular el blob a la declaración preparada.

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

Pero, en realidad, sería mejor para el rendimiento almacenar la imagen en el disco y la ruta en la base de datos.

Otra forma de hacerlo, una que uso para enviar datos de imagen en XML, es 64 codificar los datos. Lo tengo aquí como una categoría en 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 para sqlite3_stmt y para guardar el archivo en el disco en lugar de en la base de datos –

+0

Gracias, no podré probarlo hasta el lunes pero informaré. En cuanto a guardar en el disco, esto es lo que he estado haciendo en el pasado, pero ahora estoy reproduciendo y guardando las imágenes. No creía que pudiera guardar una imagen en el disco en el código? –

+0

Oh, seguro que puedes. Usted tiene el NSData: '[dataForImage writeToFile: ruta atómica: SÍ];' Cree un nombre de archivo único para su imagen y guárdelo en el directorio de documentos. Luego guarda esa ruta en la base de datos. Para cualquier cosa de más de 100 kb, es mucho mejor que almacenar el BLOB en sqlite. – Don

Cuestiones relacionadas