C++98下从SQL读取Blob图片并通过QPixmap在QGraphicsView显示
问题:从数据库读取Blob图片并在QGraphicsView中显示失败
我是C++新手,尝试从SQL数据库中读取存储在.bin文件里的Blob图片,该.bin文件以字符串形式存储Blob图片(如BM6等,每个.bin仅含3-4个字符)。点击执行读取代码的按钮后,QGraphicsView并未显示Blob图片,请问如何修改代码实现Blob图片显示?
存入数据库的代码
QPixmap p; p.load(filename); string a = "/root/QtApplication_1/file"; string b = boost::lexical_cast<std::string>(counter); string c = ".bmp"; p.save(("/root/QtApplication_1/file"+boost::lexical_cast<std::string>(counter)+".bmp").c_str(),"BMP"); std::string d = a + b + c ; std::ifstream blob_file; blob_file.open(d.c_str(), std::ios_base::binary | std::ifstream::in); driver = get_driver_instance(); con = driver->connect("localhost","",""); con->setSchema("BitmapImagesSchema"); prep_stmt = con->prepareStatement("Insert into bitmapImagesTable(`ID`,`ImageDir`,`ImagesBitMap`) values(?,?,?)"); prep_stmt->setInt(1,counter); prep_stmt->setString(2,d.c_str()); prep_stmt->setBlob(3,&blob_file); prep_stmt->executeQuery(); delete prep_stmt;
读取显示的无效代码
driver = get_driver_instance(); con = driver->connect("localhost","",""); con->setSchema("BitmapImagesSchema"); stmt = con-> createStatement(); std::istream *blobData; res = stmt->executeQuery("select `ImagesBitMap` from bitmapImagesTable where `ID`='"+boost::lexical_cast<std::string>(counter)+"'order by `ID` DESC"); while(res->last()){ blobData = res->getBlob("ImagesBitMap"); break; } std::istreambuf_iterator<char> isb = std::istreambuf_iterator<char>(*blobData); std::string blobString = std::string(isb,std::istreambuf_iterator<char>()); const char * image = blobString.c_str(); blobData->seekg(0,ios::end); size_t imagesize = blobData->tellg(); cout<<"aaa="<<image<<"\n"; QPixmap p; p.load(image); if(!widget.graphicsView_2->scene()){ QGraphicsScene *scene = new QGraphicsScene(this); widget.graphicsView_2->setScene(scene); } widget.graphicsView_2->scene()->addPixmap(p); delete res; delete stmt; delete con;
问题分析与修改方案
核心问题点
- QPixmap加载方式错误:
QPixmap::load(const char*)是用于加载本地文件路径,你将Blob的二进制内容转成字符串后传给该函数,它会把这个字符串当作文件路径去读取,必然找不到文件,导致QPixmap为空。 - 结果集读取逻辑错误:
while(res->last())的写法逻辑混乱,last()是将游标移到结果集最后一行,返回是否成功,这样的循环要么不执行,要么陷入死循环。 - 流操作无效:用
istreambuf_iterator读完Blob流后,再调用seekg已经无法获取有效数据,此时流已经处于末尾位置。
修改后的代码
driver = get_driver_instance(); con = driver->connect("localhost","",""); con->setSchema("BitmapImagesSchema"); stmt = con->createStatement(); std::istream *blobData = nullptr; res = stmt->executeQuery("select `ImagesBitMap` from bitmapImagesTable where `ID`='"+boost::lexical_cast<std::string>(counter)+"' order by `ID` DESC"); // 正确读取结果集:移动到第一行(order by DESC后即为目标行) if (res->next()) { blobData = res->getBlob("ImagesBitMap"); } else { // 未找到数据时的处理 cout << "未找到对应ID的图片数据" << endl; delete res; delete stmt; delete con; return; } // 将Blob二进制数据读取到string std::istreambuf_iterator<char> isb(*blobData), endIter; std::string blobString(isb, endIter); // 将string转为QByteArray,用QPixmap从二进制数据加载 QByteArray imageData(blobString.data(), blobString.size()); QPixmap p; // 明确指定图片格式为BMP(与存入时一致) if (!p.loadFromData(imageData, "BMP")) { cout << "图片加载失败" << endl; delete res; delete stmt; delete con; return; } // 初始化场景并显示图片 if (!widget.graphicsView_2->scene()) { QGraphicsScene *scene = new QGraphicsScene(this); widget.graphicsView_2->setScene(scene); } else { // 清空原有场景内容,避免重复添加 widget.graphicsView_2->scene()->clear(); } widget.graphicsView_2->scene()->addPixmap(p); // 确保视图适配图片大小 widget.graphicsView_2->fitInView(widget.graphicsView_2->scene()->itemsBoundingRect(), Qt::KeepAspectRatio); // 释放资源 delete res; delete stmt; if (blobData) { delete blobData; // 注意释放Blob流资源 } delete con;
额外说明
- 释放资源时别忘了删除
blobData,避免内存泄漏; - 添加
fitInView可以让图片在QGraphicsView中自适应显示; - 加载时指定
"BMP"格式,能提高加载成功率,避免QPixmap自动识别格式出错。
内容的提问来源于stack exchange,提问作者user19888430
相关产品推荐
相关产品推荐

