2010-11-18 13 views
5

Potrzebuję odczytywać i zapisywać dane BLOB do bazy danych. Oto moja tabela strukturysqlite3 wstaw i odczytaj dane BLOB w bazie danych

#define CREATE_TABLE_USERS_SQL "CREATE TABLE IF NOT EXISTS %@ (\ 
UserID INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, \ 
Name VARCHAR(50), \ 
Image BLOB);" 

Jak mogę wstawić ją do bazy danych, a następnie pobrać z niej?

Środowisko: iPhone SDK 4.1 Baza danych SQLite3.

Kod ten nie powiedzie się:

 NSData * buf2 = [[NSData alloc] init]; 
     sqlite3_column_blob(statement, 5); 
     buf2 = sqlite3_column_bytes(statement, 5); 
     user.image = [UIImage imageWithData: buf2]; 
+0

To pytanie zadaje to samo, co twoje, a odpowiedzi tam powinny zaspokoić Twoje potrzeby: http://stackoverflow.com/questions/643682/reading-andwriting-images-to-an-sqlite-db- for-iphone-use –

Odpowiedz

1

Oprócz wyboru klienta lub interfejsu programowania, wykorzystanie nie różni się od każdej innej dziedzinie strun.


[Aktualizacja] Nie miałem szczęścia do rozwijania dla iPhone jeszcze, ale ja uważam, że jest taki sam jak każdy inny zapytania SELECT lub INSERT. Pamiętaj, aby zakodować BLOB i zamknąć go pojedynczymi apostrofami ('), jak ciągi.

+0

Dodałem pytanie – yozhik

10

Niż wszystko !! Z twoja pomoc I'v rozwiązany problem i chcesz podzielić wyników dla przyszłych początkujących jak ja.)

-(void) addToDB 
{ 
    NSLog(@"\nCreating db"); 
    NSString *str = @"CREATE TABLE IF NOT EXISTS Images (image1 BLOB);"; 
    int res = SQLITE_ERROR; 


    res = sqlite3_open([@"aa.sql" UTF8String], &database); 
    res = sqlite3_exec(database, [str UTF8String], NULL, NULL, NULL); 

    sqlite3_stmt *updStmt =nil; 

    const char *sql = "INSERT INTO Images (image1) VALUES (?);"; 
    res = sqlite3_prepare_v2(database, sql, -1, &updStmt, NULL); 

    if(res!= SQLITE_OK) 
    { 
     NSLog(@"Error while creating update statement:%s", sqlite3_errmsg(database)); 
    } 

    UIImage *img = [UIImage imageNamed: @"flower.png"]; 
    NSData *imageData = [NSData dataWithData: UIImagePNGRepresentation(img)]; 

    res = sqlite3_bind_blob(updStmt, 1, [imageData bytes], [imageData length] , SQLITE_TRANSIENT); 

    if((res = sqlite3_step(updStmt)) != SQLITE_DONE) 
    { 
     NSLog(@"Error while updating: %@", sqlite3_errmsg(database)); 
     sqlite3_reset(updStmt); 
    } 

    res = sqlite3_reset(updStmt); 
    res = sqlite3_close(database); 
} 

-(void) readFromDB 
{ 
    NSLog(@"\nReading from db"); 

    NSString *query = @"SELECT image1 from Images"; 
    int res = SQLITE_ERROR; 
    int len = 0; 

    res = sqlite3_open([@"aa.sql" UTF8String], &database); 

    sqlite3_stmt *statement; 
    res = sqlite3_prepare_v2 (database, [query UTF8String], -1, &statement, nil); 

    if (res == SQLITE_OK) 
    { 
     if (sqlite3_step(statement) == SQLITE_ROW) 
     { 
      len = sqlite3_column_bytes(statement, 0); 
      NSData *imgData = [[NSData alloc] initWithBytes: sqlite3_column_blob(statement, 0) length: len];   


      UIImage *img = [[UIImage alloc] initWithData:imgData]; 

      self.view1.image = img; 

     } 
    } 
    sqlite3_finalize(statement); 

    res = sqlite3_close(database); 
} 
+0

dzięki za wysyłkę, ten kod działa dobrze.Ale kiedy zmieniam nazwę obrazu z "flower.png" na jakiś inny taki jak "xyz.png" to wyświetla poprzedni obraz w obrazie, więc możesz wskazać powód ....... –

+0

maby musisz najpierw przejść do odpowiedniego rekordu w bazie danych, a dopiero potem odczytać z niego obraz, a teraz zawsze bierze pierwszy rekord. spróbuj tego, naprawdę nie pamiętam, że to było rok temu. – yozhik

+0

w NSLog (@ "Błąd podczas tworzenia instrukcji aktualizacji:% @", sqlite3_errmsg (baza danych)); Formatowanie% s powinno być używane –

0

// ----- Wstaw obraz

- (void)setImage:(UIImage *)theImage 
{ 

    if(sqlite3_open([databasePath UTF8String],&myDatabase)==SQLITE_OK) 
    {  
    NSString *insertProgrammeSql = @"INSERT INTO imageTable (imageName) VALUES (?)"; 

sqlite3_stmt *statement; 

    if (sqlite3_prepare_v2(myDatabase, [insertProgrammeSql cStringUsingEncoding:NSUTF8StringEncoding], -1, &statement, NULL) == SQLITE_OK) { 

    NSData *imageData = UIImagePNGRepresentation(theImage); 

     sqlite3_bind_blob(statement, 1, [imageData bytes], [imageData length], SQLITE_TRANSIENT); 

    sqlite3_step(statement); 
} 
    sqlite3_close(myDatabase); 
// return YES;  
} 


    } 

// ---- ---- get image

-(UIImage *)getImage 

    { 

    UIImage *image = nil; 


if(sqlite3_open([databasePath UTF8String],&myDatabase)==SQLITE_OK) 
{ 

NSString *selectSql = @"SELECT image FROM imageTable"; 

sqlite3_stmt *statement; 
if (sqlite3_prepare_v2(myDatabase, [selectSql UTF8String], -1, &statement, NULL) == SQLITE_OK) 
{ 
    int length = sqlite3_column_bytes(statement, 0); 
    NSData *imageData = [NSData dataWithBytes:sqlite3_column_blob(statement, 0) length:length]; 

    image = [UIImage imageWithData:imageData]; 



    sqlite3_finalize(statement); 

    } 
    sqlite3_close(myDatabase); 
    } 
return image; 
} 
0

Kod ten nie powiedzie się:

NSData * buf2 = [[NSData alloc] init]; 
    sqlite3_column_blob(statement, 5); 
    buf2 = sqlite3_column_bytes(statement, 5); 
    user.image = [UIImage imageWithData: buf2]; 

Wywołujesz funkcje SQLite w prawidłowej kolejności. Zgodnie z SQLite docs:

Najbezpieczniejszym i najłatwiejsze do zapamiętania polityka jest do wywołania tych procedur w jeden z następujących sposobów:

  • sqlite3_column_text(), a następnie sqlite3_column_bytes()
  • sqlite3_column_blob(), a następnie sqlite3_column_bytes()
  • sqlite3_column_text16(), a następnie sqlite3_column_bytes16()

Innymi słowy, należy zadzwonić sqlite3_column_text(), sqlite3_column_blob() lub sqlite3_column_text16() pierwsza zmusić wynik do pożądanego formatu, a następnie powołać sqlite3_column_bytes() lub sqlite3_column_bytes16(), aby znaleźć wielkość wyniku .Nie mieszaj wywołań z sqlite3_column_text() lub sqlite3_column_blob() z wywołaniami do sqlite3_column_bytes16() i nie łącz połączeń z sqlite3_column_text16() z wywołaniami do sqlite3_column_bytes().

Jednak buff2 jest liczbą całkowitą, a nie wskaźnikiem danych. sqlite3_column_bytes informuje, ile bajtów znajduje się w obszarze typu blob.

Powiązane problemy