2010-07-23 15 views
6

Do tej pory udało mi się stworzyć tę metodę do wstawiania do bazy danych SQLite na iPhone:Wkładanie NSData do SQLite na 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); 
} 

Teraz patrzę na przechowywanie obrazu w bazie danych. Do tej pory mam found this:

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

ale mam kłopoty próbuje wstawić ten NSData do tablicy char, która sprawia, że ​​SQLStatement. Czy ktoś ma pomysł, jak to zrobić?

(Mam pole w bazie danych typu blob dla tego).

Dzięki

+1

Do * not * put BLOBs w bazie danych. Jest okropnie nieefektywny na wszystkich poziomach. Zapisz ścieżkę w bazie danych i umieść obiekt BLOB w systemie plików. – bbum

+0

Chciałbym * bardzo * polecić korzystanie z opakowania bazy danych Flying Meat, które rozwiązało już wszystkie te problemy i jest * znacznie * prostsze w użyciu: http://github.com/ccgus/fmdb –

Odpowiedz

9

użyłbym sqlite3_stmt zamiast napisu. Następnie można użyć sqlite3_bind_blob, aby powiązać obiekt blob z przygotowanym oświadczeniem.

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

Ale najlepiej, gdyby wydajność przechowywania obrazu na dysku i ścieżki w bazie danych.

Innym sposobem na zrobienie tego, którego używam do wysyłania danych obrazu w XML, jest oparcie 64 kodu danych. Mam go tutaj jako kategorię na 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 dla sqlite3_stmt i do zapisania pliku na dysk zamiast w bazie danych –

+0

Dzięki, nie będę mógł tego wypróbować do poniedziałku, ale zgłosimy się z powrotem. Jeśli chodzi o zapisywanie na dysku, robię to w przeszłości, ale teraz przesyłam strumieniowo i zapisuję obrazy. Nie sądziłem, że możesz zapisać obraz na dysk w kodzie? –

+0

Och, oczywiście, że możesz. Masz NSData: '[dataForImage writeToFile: ścieżka atomicznie: TAK];' Zbuduj unikalną nazwę pliku dla swojego obrazu i zapisz go w katalogu dokumentów. Następnie zapisz tę ścieżkę w bazie danych. Cokolwiek ponad 100 kb lub więcej, jest znacznie lepsze niż przechowywanie obiektu BLOB w sqlite. – Don