试图将图像存储到 sqlite 中,当我尝试检索它时,它是一个字节而不是 200 万字节
Tried to store a image into sqlite and when I try to retrieve it it's one byte instead of 2 million bytes
当我尝试将图像存储到 sqlite 中时,我已将该图像转换为 NSData,并且 imageData 中有超过 2,000,000 字节。
当我尝试从 sqlite 数据库中检索它时,它变成了一个字节。
这是我的代码:
将图像插入 sqlite:
-(void)INSERTCLAIMATTACHMENT:(NSString *)tablename
PARENTID:(long long)parentid
ATTACHMENTCONTENT:(UIImage *)attachmentimage
ATTACHMENTNAME:(NSString *)attachmentname
{
sqlite3_stmt *statement;
const char *dbPath = [_databasePath UTF8String];
Global * g = [[Global alloc]init];
NSData *imageData = [[NSData alloc]init];
imageData = UIImagePNGRepresentation(attachmentimage);
if(sqlite3_open(dbPath, &_DB) == SQLITE_OK)
{
NSString *insertSQL = [NSString stringWithFormat:@"INSERT INTO CLAIM_ATTACHMENT_ITEM ('PARENT_ID', 'CLAIM_ATTACHMENT_CONTENT', 'CLAIM_ATTACHMENT_NAME', 'CLAIM_ATTACHMENT_SIZE') VALUES ('%lld', '?', '%@', '%lu')", parentid,attachmentname, [imageData length]];
const char *insert_statement = [insertSQL UTF8String];
if(sqlite3_prepare_v2(_DB,insert_statement, -1, &statement, NULL) == SQLITE_OK)
{
sqlite3_bind_blob(statement, 2, [imageData bytes], [imageData length], SQLITE_TRANSIENT);
if(sqlite3_step(statement) == SQLITE_DONE)
{
[g showCustomAlertView:@"Successfull" message:@"Attachment has been added into database."];
}
else{
[g showCustomAlertView:@"Failure" message:[NSString stringWithFormat:@"%s", sqlite3_errmsg(_DB)]];
}
}
else{
[g showCustomAlertView:@"Failure" message:[NSString stringWithFormat:@"%s", sqlite3_errmsg(_DB)]];
}
}
else{
[g showCustomAlertView:@"Failure" message:[NSString stringWithFormat:@"%s", sqlite3_errmsg(_DB)]];
}
sqlite3_close(_DB);
}
从 sqlite 中检索图像
-(NSMutableArray *)SELECTATTACHMENTFROMCLAIMATTACHMENTITEM:(long long)rowID
{
sqlite3_stmt *statement;
const char *dbPath = [_databasePath UTF8String];
Global * g = [[Global alloc]init];
NSMutableArray *attachmentArray = [[NSMutableArray alloc]init];
if(sqlite3_open(dbPath, &_DB) == SQLITE_OK)
{
NSString *querySQL = [NSString stringWithFormat:@"SELECT * FROM CLAIM_ATTACHMENT_ITEM WHERE PARENT_ID = '%lld'", rowID];
const char *query_Statement = [querySQL UTF8String];
if(sqlite3_prepare_v2(_DB, query_Statement, -1, &statement, NULL) == SQLITE_OK)
{
while(sqlite3_step(statement) == SQLITE_ROW)
{
AttachmentItem * attachment = [[AttachmentItem alloc]init];
NSData *attachmentImageData = [[NSData alloc]initWithBytes:sqlite3_column_blob(statement, 2) length:sqlite3_column_bytes(statement, 2)];
UIImage *attachmentImage = [UIImage imageWithData:attachmentImageData];
NSString *attachmentName = [[NSString alloc]initWithUTF8String:sqlite3_column_text(statement, 3)];
attachment.attachmentImage = attachmentImage;
attachment.attachmentName = attachmentName;
[attachmentArray addObject:attachment];
}
}
else
{
[g showCustomAlertView:@"Failure" message:[NSString stringWithFormat:@"%s", sqlite3_errmsg(_DB)]];
}
}
else
{
[g showCustomAlertView:@"Failure" message:[NSString stringWithFormat: @"%s",sqlite3_errmsg(_DB)]];
}
sqlite3_close(_DB);
return attachmentArray;
}
发生了什么?为什么图像数据对我来说缩成了一个字节:(
我猜 blob 可能无法存储那么大的数据?
您对 sqlite_bind_blob
的调用传递了错误的字段索引。 INSERT
语句中只有一个 ?
,因此索引应该是 1
,而不是 2
。
sqlite3_bind_blob(statement, 1, [imageData bytes], [imageData length], SQLITE_TRANSIENT);
此外,您需要删除 INSERT
语句中 ?
的引号:
NSString *insertSQL = [NSString stringWithFormat:@"INSERT INTO CLAIM_ATTACHMENT_ITEM ('PARENT_ID', 'CLAIM_ATTACHMENT_CONTENT', 'CLAIM_ATTACHMENT_NAME', 'CLAIM_ATTACHMENT_SIZE') VALUES ('%lld', ?, '%@', '%lu')", parentid,attachmentname, [imageData length]];
使用 ?
结合适当的 sqlite3_bind_xxx
语句而不是使用 stringWithFormat:
构建查询的主要原因是为您正确引用和转义了值。
VALUES ('%lld', '?', '%@', '%lu')
%
替换是文本的,但 ?
由 SQL 引擎处理,并且仅当参数标记出现在它是表达式的位置时才起作用。
加上引号,'?'
只是一个包含单个字符 ?
.
的字符串
你必须写不带引号的参数:
[NSString stringWithFormat:@"INSERT ... VALUES ('%lld', ?, '%@', '%lu')", ...];
而且这条语句只有一个SQL参数,所以它的索引必须是1,而不是2。
当我尝试将图像存储到 sqlite 中时,我已将该图像转换为 NSData,并且 imageData 中有超过 2,000,000 字节。
当我尝试从 sqlite 数据库中检索它时,它变成了一个字节。
这是我的代码:
将图像插入 sqlite:
-(void)INSERTCLAIMATTACHMENT:(NSString *)tablename
PARENTID:(long long)parentid
ATTACHMENTCONTENT:(UIImage *)attachmentimage
ATTACHMENTNAME:(NSString *)attachmentname
{
sqlite3_stmt *statement;
const char *dbPath = [_databasePath UTF8String];
Global * g = [[Global alloc]init];
NSData *imageData = [[NSData alloc]init];
imageData = UIImagePNGRepresentation(attachmentimage);
if(sqlite3_open(dbPath, &_DB) == SQLITE_OK)
{
NSString *insertSQL = [NSString stringWithFormat:@"INSERT INTO CLAIM_ATTACHMENT_ITEM ('PARENT_ID', 'CLAIM_ATTACHMENT_CONTENT', 'CLAIM_ATTACHMENT_NAME', 'CLAIM_ATTACHMENT_SIZE') VALUES ('%lld', '?', '%@', '%lu')", parentid,attachmentname, [imageData length]];
const char *insert_statement = [insertSQL UTF8String];
if(sqlite3_prepare_v2(_DB,insert_statement, -1, &statement, NULL) == SQLITE_OK)
{
sqlite3_bind_blob(statement, 2, [imageData bytes], [imageData length], SQLITE_TRANSIENT);
if(sqlite3_step(statement) == SQLITE_DONE)
{
[g showCustomAlertView:@"Successfull" message:@"Attachment has been added into database."];
}
else{
[g showCustomAlertView:@"Failure" message:[NSString stringWithFormat:@"%s", sqlite3_errmsg(_DB)]];
}
}
else{
[g showCustomAlertView:@"Failure" message:[NSString stringWithFormat:@"%s", sqlite3_errmsg(_DB)]];
}
}
else{
[g showCustomAlertView:@"Failure" message:[NSString stringWithFormat:@"%s", sqlite3_errmsg(_DB)]];
}
sqlite3_close(_DB);
}
从 sqlite 中检索图像
-(NSMutableArray *)SELECTATTACHMENTFROMCLAIMATTACHMENTITEM:(long long)rowID
{
sqlite3_stmt *statement;
const char *dbPath = [_databasePath UTF8String];
Global * g = [[Global alloc]init];
NSMutableArray *attachmentArray = [[NSMutableArray alloc]init];
if(sqlite3_open(dbPath, &_DB) == SQLITE_OK)
{
NSString *querySQL = [NSString stringWithFormat:@"SELECT * FROM CLAIM_ATTACHMENT_ITEM WHERE PARENT_ID = '%lld'", rowID];
const char *query_Statement = [querySQL UTF8String];
if(sqlite3_prepare_v2(_DB, query_Statement, -1, &statement, NULL) == SQLITE_OK)
{
while(sqlite3_step(statement) == SQLITE_ROW)
{
AttachmentItem * attachment = [[AttachmentItem alloc]init];
NSData *attachmentImageData = [[NSData alloc]initWithBytes:sqlite3_column_blob(statement, 2) length:sqlite3_column_bytes(statement, 2)];
UIImage *attachmentImage = [UIImage imageWithData:attachmentImageData];
NSString *attachmentName = [[NSString alloc]initWithUTF8String:sqlite3_column_text(statement, 3)];
attachment.attachmentImage = attachmentImage;
attachment.attachmentName = attachmentName;
[attachmentArray addObject:attachment];
}
}
else
{
[g showCustomAlertView:@"Failure" message:[NSString stringWithFormat:@"%s", sqlite3_errmsg(_DB)]];
}
}
else
{
[g showCustomAlertView:@"Failure" message:[NSString stringWithFormat: @"%s",sqlite3_errmsg(_DB)]];
}
sqlite3_close(_DB);
return attachmentArray;
}
发生了什么?为什么图像数据对我来说缩成了一个字节:( 我猜 blob 可能无法存储那么大的数据?
您对 sqlite_bind_blob
的调用传递了错误的字段索引。 INSERT
语句中只有一个 ?
,因此索引应该是 1
,而不是 2
。
sqlite3_bind_blob(statement, 1, [imageData bytes], [imageData length], SQLITE_TRANSIENT);
此外,您需要删除 INSERT
语句中 ?
的引号:
NSString *insertSQL = [NSString stringWithFormat:@"INSERT INTO CLAIM_ATTACHMENT_ITEM ('PARENT_ID', 'CLAIM_ATTACHMENT_CONTENT', 'CLAIM_ATTACHMENT_NAME', 'CLAIM_ATTACHMENT_SIZE') VALUES ('%lld', ?, '%@', '%lu')", parentid,attachmentname, [imageData length]];
使用 ?
结合适当的 sqlite3_bind_xxx
语句而不是使用 stringWithFormat:
构建查询的主要原因是为您正确引用和转义了值。
VALUES ('%lld', '?', '%@', '%lu')
%
替换是文本的,但 ?
由 SQL 引擎处理,并且仅当参数标记出现在它是表达式的位置时才起作用。
加上引号,'?'
只是一个包含单个字符 ?
.
你必须写不带引号的参数:
[NSString stringWithFormat:@"INSERT ... VALUES ('%lld', ?, '%@', '%lu')", ...];
而且这条语句只有一个SQL参数,所以它的索引必须是1,而不是2。