2010-07-23 4 views
6

Jusqu'à présent, j'ai réussi à créer cette méthode pour insérer dans une base de données SQLite sur l'iPhone:Insertion NSData dans SQLite sur l'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); 
} 

Maintenant, je suis à la recherche à stocker une image dans la base de données. Jusqu'à présent, j'ai found this:

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

Mais je vais avoir du mal à essayer d'insérer ce NSData dans le tableau de caractères qui rend le instructionSQL. Quelqu'un a une idée de comment faire ça?

(J'ai un champ dans la base de données de type blob pour cela).

Merci

+1

Ne pas * mettre * BLOBs dans la base de données. C'est horriblement inefficace à tous les niveaux. Enregistrez un chemin dans la base de données et placez le BLOB dans le système de fichiers. – bbum

+0

Je recommanderais fortement l'utilisation du wrapper de base de données Flying Meat, qui a déjà résolu tous ces problèmes pour vous et est * beaucoup * plus simple à utiliser: http://github.com/ccgus/fmdb –

Répondre

9

j'utiliser sqlite3_stmt au lieu d'une chaîne. Ensuite, vous pouvez utiliser sqlite3_bind_blob pour lier le blob à l'instruction préparée. Mais, vraiment, il serait préférable pour les performances de stocker l'image sur le disque et le chemin dans la base de données.

Une autre façon de le faire, que j'utilise pour envoyer des données d'image en XML, est de coder en base 64 les données. Je l'ai ici en tant que catégorie sur 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 pour sqlite3_stmt et pour enregistrer le fichier sur le disque au lieu de dans la base de données –

+0

Merci, je ne serai pas en mesure d'essayer jusqu'à lundi, mais je vais signaler. En ce qui concerne l'enregistrement sur disque, c'est ce que j'ai fait par le passé, mais je suis en train de diffuser et d'enregistrer les images. Je ne pensais pas que vous pourriez enregistrer une image sur le disque dans le code? –

+0

Oh, bien sûr que vous pouvez. Vous avez le NSData: '[dataForImage writeToFile: chemin atomiquement: YES];' Construire un nom de fichier unique pour votre image et l'enregistrer dans le répertoire de documents. Puis enregistrez ce chemin dans la base de données. Pour quelque chose de plus de 100 Ko, c'est beaucoup mieux que de stocker le BLOB dans sqlite. – Don