2010-07-23 33 views
6

Cho đến nay tôi đã quản lý để tạo ra phương pháp này để chèn vào một cơ sở dữ liệu SQLite trên iPhone:Chèn NSData vào SQLite trên 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); 
} 

Bây giờ tôi nhìn vào lưu trữ một hình ảnh trong cơ sở dữ liệu. Cho đến nay tôi đã found this:

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

Nhưng tôi đang gặp rắc rối cố gắng để chèn NSData này vào mảng char mà làm cho sqlStatement. Bất cứ ai cũng có một ý tưởng làm thế nào để làm điều này?

(Tôi có một trường trong cơ sở dữ liệu loại blob cho việc này).

Cảm ơn

+1

Không * đặt BLOB vào cơ sở dữ liệu. Đó là khủng khiếp không hiệu quả trên tất cả các cấp. Lưu trữ một đường dẫn trong cơ sở dữ liệu và đưa BLOB vào hệ thống tập tin. – bbum

+0

Tôi sẽ * đánh giá cao * khuyên bạn nên sử dụng trình bao bọc cơ sở dữ liệu Flying Meat, đã giải quyết tất cả các vấn đề này cho bạn rồi và * nhiều * đơn giản hơn để sử dụng: http://github.com/ccgus/fmdb –

Trả lời

9

Tôi sẽ sử dụng sqlite3_stmt thay vì chuỗi. Sau đó, bạn có thể sử dụng sqlite3_bind_blob để liên kết đốm màu với câu lệnh đã chuẩn bị.

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

Nhưng, thực sự, sẽ tốt nhất cho hiệu suất lưu trữ hình ảnh trên đĩa và đường dẫn trong cơ sở dữ liệu.

Một cách khác để làm điều đó, một cách tôi sử dụng để gửi dữ liệu hình ảnh trong XML, là cơ sở 64 mã hóa dữ liệu. Tôi có ở đây dưới dạng danh mục trên 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 cho sqlite3_stmt và để lưu tệp vào đĩa thay vì trong cơ sở dữ liệu –

+0

Cảm ơn, tôi sẽ không thể thử điều đó cho đến thứ Hai nhưng tôi sẽ báo cáo lại. Về việc lưu vào đĩa, đây là những gì tôi đã làm trong quá khứ nhưng bây giờ tôi đang phát và lưu hình ảnh. Tôi không nghĩ rằng bạn có thể lưu một hình ảnh vào đĩa trong mã? –

+0

Ồ, chắc chắn bạn có thể. Bạn có NSData: '[dataForImage writeToFile: path atomically: YES];' Xây dựng một tên tập tin duy nhất cho hình ảnh của bạn và lưu nó vào thư mục tài liệu. Sau đó lưu đường dẫn đó trong cơ sở dữ liệu. Đối với bất cứ điều gì hơn 100 kb hoặc hơn, nó tốt hơn nhiều so với lưu trữ BLOB trong sqlite. – Don

Các vấn đề liên quan