2009-03-13 3 views
22

Ich habe eine SQLite DB eingerichtet, die derzeit NSString s perfekt liest und schreibt. Ich möchte auch ein Bild in der Datenbank speichern und später abrufen. Ich habe ein wenig über die Verwendung von NSData und Codierung des Bildes gelesen, aber ich bin mir nicht ganz sicher, was die Syntax für das ist, was ich tun möchte. Alle Codefragmente oder Beispiele würden sehr geschätzt werden.Lesen und Schreiben von Bildern in eine SQLite DB für iPhone Verwendung

Mein aktueller Prozess geht so: UIImagePickerController -> Benutzer wählt Bild von Fotos ->Jetzt möchte ich dieses Bild nehmen und speichern sie in der DB

-> chosenImage zum Beispiel von UIImageView gesetzt Ich sollte erwähnen, dass dieser Anruf schließlich durch einen Anruf an einen Remote-Server ersetzt wird. Nicht sicher, ob dies einen Unterschied in Bezug auf die Leistung macht.

Antwort

9

Eine Option (und im Allgemeinen in SQL bevorzugt) besteht darin, das Image in eine Datei auf dem System zu schreiben und den Pfad (oder eine andere Art von Bezeichner) in der Datenbank zu speichern.

+0

Ich bin ratlos wirklich, warum jemand die binären im DB würde speichern. Scheint mir verrückt. Ich denke also, dass die Metadaten in der DB der beste Fall sind. –

+0

Können Sie mir ein Codebeispiel für so etwas zeigen? Ich kann sehen, wie das Speichern in einer Datei von Vorteil sein könnte. – Jeff

+1

nach ein paar Tagen googeln. Ich habe diese Idee realisiert und umgesetzt. Ich poste etwas Code, wenn jemand es braucht. – Jeff

31

Sie müssen das in Ihrem UIImageView gehostete UIImage in ein binäres BLOB zum Speichern in SQLite konvertieren. Um dies zu erreichen, können Sie die folgenden Schritte aus:

NSData *dataForImage = UIImagePNGRepresentation(cachedImage); 
sqlite3_bind_blob(yourSavingSQLStatement, 2, [dataForImage bytes], [dataForImage length], SQLITE_TRANSIENT); 

Dies wird eine PNG Darstellung des Bildes erzeugen, speichert es in einer NSData Instanz, und dann bindet die Bytes aus dem NSData als BLOB für das zweite Argument in Ihre SQL-Abfrage. Verwenden Sie UIImageJPEGRepresentation in obigem, um in diesem Format zu speichern, wenn Sie möchten. Sie müssen eine BLOB-Spalte zur entsprechenden Tabelle in Ihrer SQLite-Datenbank hinzufügen.

dieses Bild abzurufen, können Sie die folgende verwenden:

NSData *dataForCachedImage = [[NSData alloc] initWithBytes:sqlite3_column_blob(yourLoadingSQLStatement, 2) length: sqlite3_column_bytes(yourLoadingSQLStatement, 2)];  
self.cachedImage = [UIImage imageWithData:dataForCachedImage]; 
[dataForCachedImage release]; 
+0

Danke Brad! Ich werde es später am Nachmittag versuchen. Sieht so aus, als ob es den Trick tun könnte. – Jeff

+0

Ich erkannte, das ist nicht wollen, ich wollte tun. Speichern Sie die Datei in eine URL auf dem Server ist ein besserer Weg zu gehen. – Jeff

+2

Wenn das am besten für die Anwendung funktioniert, dann ist das der Weg zu gehen. Ich habe Bilder in der Datenbank gespeichert, als ich eine einzelne Datei wollte, die ich in einer Anwendung bündeln könnte, die einige Startdaten enthalten würde. Es hat das Dateisystem etwas sauberer gemacht. –

2

zu SQLite DB Bild Schreiben

if(myImage != nil){ 
    NSData *imgData = UIImagePNGRepresentation(myImage); 
    sqlite3_bind_blob(update_stmtement, 6, [imgData bytes], [imgData length], NULL);  
    } 
    else { 
     sqlite3_bind_blob(update_stmtement, 6, nil, -1, NULL); 
    } 

Von SQLite DB Lesen:

NSData *data = [[NSData alloc] initWithBytes:sqlite3_column_blob(init_statement, 6) length:sqlite3_column_bytes(init_statement, 6)]; 
     if(data == nil) 
      NSLog(@"No image found."); 
     else 
      self.pictureImage = [UIImage imageWithData:data]; 
9

Empfehlung von Apple ist nicht um BLOBs in SQLite-Datenbanken zu speichern, die größer als ~ 2 Kilobyte sind.

SQLite organisiert Datenbanken in Seiten. Jede Seite ist 4 Kilobyte groß. Wenn Sie Daten aus der SQLite-Datenbankdatei lesen, lädt sie diese Seiten in einen internen Seitencache. Auf dem iPhone denke ich, dass dieser Cache standardmäßig 1 Megabyte groß ist. Dies macht das Lesen benachbarter Datensätze sehr schnell, da sie sich wahrscheinlich bereits im Seitencache befinden.

Wenn SQLite Ihren Datenbankeintrag in den Speicher liest, liest er den gesamten Datensatz und alle Seiten, die er belegt. Wenn Ihr Datensatz also ein BLOB enthält, könnte er viele Seiten belegen, und Sie werden vorhandene Seiten aus dem Cache auswerfen und durch die Seiten Ihres BLOB-Datensatzes ersetzen.

Dies ist nicht so schlimm, wenn Sie nur scannen und alle Ihre BLOBS laden, um etwas mit ihnen zu tun (zeigen Sie sie zum Beispiel). Wenn Sie jedoch eine Abfrage ausführen, bei der Sie nur Daten abrufen möchten, die sich in derselben Zeile wie das BLOB befinden, wäre diese Abfrage wesentlich langsamer, als wenn der Datensatz das große BLOB nicht enthält.

Sie sollten Ihre BLOB-Daten also mindestens in einer separaten Tabelle speichern.ZB:

CREATE TABLE blobs (id INTEGER PRIMARY KEY, data BLOB); 
CREATE TABLE photos (id INTEGER PRIMARY KEY, name TEXT, blob_id INTEGER, 
    FOREIGN KEY(blob_id) REFERENCES blobs(id)); 

Oder besser noch, speichern Sie die BLOB-Daten als Dateien außerhalb der SQLite-Datenbank.

Beachten Sie, dass es möglich sein kann, die Seiten-Cache-Größe mit SQL PRAGMA statements zu optimieren (wenn Sie nicht Coredata verwenden).

+0

Wo empfiehlt Apple das? – Bill

0

Die beste Vorgehensweise ist es, das Bild und speichern sie in der Datenbank oder im Dateisystem zu komprimieren. Wenn Sie nicht über die Auflösung des Bildes kümmern können Sie voran gehen und sogar die Größe des Bildes durch die Verwendung:

UIGraphicsBeginImageContext(newSize); 
    [image drawInRect:CGRectMake(0,0,newSize.width,newSize.height)]; 
    UIImage* newImage = UIGraphicsGetImageFromCurrentImageContext();  
    UIGraphicsEndImageContext(); 

Danach Sie UIImageJPEGRepresentation für JPEG-Bilder mit einem Wert von „0“ für maximale Kompression verwenden können . Oder Sie können UIImagePNGRepresentation für PNG-Bilder verwenden

0

sollten Sie zuerst Bild auf Dateisystem schreiben. und nimm dann den Bildpfad und speichere diesen Bildpfad (URL) als TEXT in sqlite.

Verwandte Themen