sqlite3_bind_blob renvoit un nsdata invalide (pas la même taille que le nsdata d'origine)

Je sauvegarde une image sous forme de nsdata dans le base sqlite:



UIImage *imageCourante = [UIImage imageNamed: @img.png];
NSData *imageData = UIImageJPEGRepresentation(imageCourante, 0,7);

if (!sqlite3_open([dbPath UTF8String], &database) == SQLITE_OK) {
        NSLog(@connexion impossible à  la base: '%s,sqlite3_errmsg(database));
    }
    else{
        NSString *insertSQL = [NSString stringWithFormat:@insert into table (id,imgData) values ('2222222','%@')",imageData];
        
        const char *insert_stmt = [insertSQL UTF8String];
        sqlite3_prepare_v2(database, insert_stmt,-1, &statement, NULL);
        
        NSLog(@erreur 0 : '%s,sqlite3_errmsg(database));
        
        if (sqlite3_prepare_v2(database, insert_stmt,-1, &statement, NULL)) {
            NSLog(@erreur 1 : '%s,sqlite3_errmsg(database));
            
        }
        
        if (sqlite3_step(statement) == SQLITE_DONE)
        {
            NSLog(@saveData: yes);
        }
       
        sqlite3_reset(statement);
}

En récupérance le nsdata comme ceci:



NSData *data = [[NSData alloc] initWithBytes:sqlite3_column_blob(statement, 7) length:length];

data n'a pas la même taille que l'image d'origine (imageData). Du coup, quand j'essaie de l'afficher rien ne s'affiche.


 


Aurai-je zapper une étape ?


 


merci


Réponses

  • Avec ta méthode tu ne stockes pas l'image mais une description de l'image (format %@ dans stringWithFormat).


    Pour stocker une donnée binaire il faut mettre ? comme valeur dans la chaà®ne de caractères insertSQL puis relier ce paramètre à  la donnée binaire [NSData bytes] par sqlite3_bind_blob.


  • zozorzozor Membre
    août 2013 modifié #3

    merci pour votre reponse.


    en fessant



    NSString *insertSQL = [NSString stringWithFormat:@insert into table (id,imgData) values (?,?)];

    sqlite3_bind_text(statement, 0, [@2222222 UTF8String], -1, NULL);
    sqlite3_bind_blob(statement, 7, [imageData bytes], [imageData length], SQLITE_TRANSIENT);

    j'ai cette erreur:



    table.id may not be NULL

    idem quand je remplace null par SQLITE_TRANSIENT pour l'id


  • C'est normal.


    sqlite3_bind_text attend un pointeur sur une chaà®ne de caractères C, et tu lui passes un pointeur sur un objet NSString.


    De plus il peut y avoir un autre problème si le champ id n'est pas défini comme texte mais comme une donnée numérique.


     


    Le plus simple est de laisser '2222222' dans la string insertSQL à  la place de ?.


    Une autre solution est de passer "2222222" à  sqlite3_bind_text à  la place de [@2222222 UTF8String].


  • j'ai fait comme ceci:



    NSString *insertSQL = [NSString stringWithFormat:@insert into table (id, imgData) values ('2222222',?)];

    NSLog(@[imageData bytes] : %lu,(unsigned long)[imageData bytes]);
    sqlite3_bind_blob(statement, 7, [imageData bytes], [imageData length], SQLITE_TRANSIENT);

    NSLog(@%s,sqlite3_errmsg(database));

    j'ai une erreur:



    bind or column index out of range

    bien sûr table a 9 colonnes et imgData est en 8eme position.


  • Ce n'est pas le 7ème paramètre de l'instruction d'insertion que tu spécifies, c'est le premier (puisqu'il n'y en a qu'un).


    Il faut remplacer 7 par 1.


  • ok merci je n'ai plus d'erreur. mais la donnée retournée avec cette instruction :



    NSData *data = [[NSData alloc] initWithBytes:sqlite3_column_blob(statement, 7) length:sqlite3_column_bytes(statement, 7)];

    est null (data.length = 0)


  • Si ta donnée est en 8ème position, et si dans l'instruction (select, je suppose) du statement les données sont dans le même ordre que dans la table, alors il faut remplacer 7 par 8 (deux fois).


  • mais dans la table le premier index est 0 et non 1. Alors en commençant par 0 index 7 est bien en 8eme position. la preuve



    sqlite3_column_text(statement, 8)]

    renvoit la valeur de l'index 8 (9eme position)


  • Ha oui ! Exact.


    La numérotation des index n'est la même dans bind et dans column.


     


    Comment est initialisé le statement ?



  • Comment est initialisé le statement ?


     


    vous parler de quelle instruction ?

  • Tu appelles sqlite3_column_blob un premier paramètre dénommé statement. Ce paramètre a du être initialisé auparavant par un appel  à  sqlite3_prepare_v2 ou une fonction apparentée.


    Et donc je parle de cette instruction.


     


    C'est une règle générale. Si l'appel d'une fonction ne marche pas (ici sqlite3_column_blob), c'est que :


    - soit la fonction est buggée (et on supposer qu'ici ce n'est pas le cas)


    - soit les paramètres qui lui sont passés sont erronés.



  • NSString *insertSQL2 = [NSString stringWithFormat:@select * from table];

    const char *insert_stmt2 = [insertSQL2 UTF8String];
    sqlite3_prepare_v2(database, insert_stmt2,-1, &statement, NULL);
  • Tu n'as pas fait un sqlite3_step pour exécuter ta requête ? 


  • effectivement j'ai oublié d'exécuter la requete avec sqlite3_step. Maintenant tout fonctionne.


    Merci jpimbert


     


    sinon comment marque un sujet comme résolu dans ce forum ?




  •  


    sinon comment marque un sujet comme résolu dans ce forum ?




     


    Bouton Modifier, puis il doit y avoir un truc du genre "Editeur complet" ou "Avancé" et tu peux changer le titre du sujet en insérant [Résolu] devant.

Connectez-vous ou Inscrivez-vous pour répondre.