如何将图像存储为 Sqlite 中的 blob 以及如何检索它?

Posted

技术标签:

【中文标题】如何将图像存储为 Sqlite 中的 blob 以及如何检索它?【英文标题】:how to store Image as blob in Sqlite & how to retrieve it? 【发布时间】:2011-11-11 23:28:09 【问题描述】:

我想将图像(来自 url)存储到 sqlite 数据库中。

为此我使用:

db = new DataBase(getApplicationContext());
URL url = new URL("http://sree.cc/wp-content/uploads/schogini_team.png");
URLConnection ucon = url.openConnection();
InputStream is = ucon.getInputStream();
BufferedInputStream bis = new BufferedInputStream(is,128);
ByteArrayBuffer barb= new ByteArrayBuffer(128);

int current = 0;
while ((current = bis.read()) != -1) 
    barb.append((byte) current);


ContentValues filedata= new ContentValues();

filedata.put(DataBase.IMG_SRC,barb.toByteArray());

db.insert(DataBase.Table_Img, null, filedata);

Insert()

public void insert(String tableImg, Object object,
        ContentValues dataToInsert) 
    // TODO Auto-generated method stub
    String sql = "INSERT INTO "+tableImg+" ("+ID+","+IMG_SRC+") " +
            "VALUES ('"+1+"','"+dataToInsert+"')";
    db.execSQL(sql);

对于图像的检索:

Cursor cursor = db.selectDataToShow(DataBase.Table_Img, DataBase.IMG_SRC);

byte[] imageByteArray=cursor.getBlob(cursor.getColumnIndex(DataBase.IMG_SRC));      
cursor.close();

ByteArrayInputStream imageStream = new ByteArrayInputStream(imageByteArray);
Bitmap theImage = BitmapFactory.decodeStream(imageStream);

System.out.println(">>>>>>>>>>>>>>>>>>>>>> "+theImage);

所以我在这里得到了null

在我的数据库中,图像的值存储为:Image=[B@43e5ac48]

【问题讨论】:

在获取 db 时我得到的不完全是 byte[]..... 有什么帮助吗? 【参考方案1】:

这是我用于我的应用程序的代码

此代码将从 url 获取图像并将其转换为字节数组

byte[] logoImage = getLogoImage(IMAGEURL);

private byte[] getLogoImage(String url)
     try 
             URL imageUrl = new URL(url);
             URLConnection ucon = imageUrl.openConnection();

             InputStream is = ucon.getInputStream();
             BufferedInputStream bis = new BufferedInputStream(is);

             ByteArrayBuffer baf = new ByteArrayBuffer(500);
             int current = 0;
             while ((current = bis.read()) != -1) 
                  baf.append((byte) current);
             

             return baf.toByteArray();
      catch (Exception e) 
          Log.d("ImageManager", "Error: " + e.toString());
     
     return null;

为了将图像保存到数据库,我使用了此代码。

 public void insertUser()
        SQLiteDatabase db = dbHelper.getWritableDatabase();
        String delSql = "DELETE FROM ACCOUNTS";
        SQLiteStatement delStmt = db.compileStatement(delSql);
        delStmt.execute();

        String sql = "INSERT INTO ACCOUNTS (account_id,account_name,account_image) VALUES(?,?,?)";
        SQLiteStatement insertStmt = db.compileStatement(sql);
        insertStmt.clearBindings();
        insertStmt.bindString(1, Integer.toString(this.accId));
        insertStmt.bindString(2,this.accName);
        insertStmt.bindBlob(3, this.accImage);
        insertStmt.executeInsert();
        db.close();

要检索图像,这是我使用的代码。

public Account getCurrentAccount() 
    SQLiteDatabase db = dbHelper.getWritableDatabase();
    String sql = "SELECT * FROM ACCOUNTS";
    Cursor cursor = db.rawQuery(sql, new String[] );

    if(cursor.moveToFirst())
        this.accId  = cursor.getInt(0);
        this.accName = cursor.getString(1);
        this.accImage = cursor.getBlob(2);
    
    if (cursor != null && !cursor.isClosed()) 
        cursor.close();
    
    db.close();
    if(cursor.getCount() == 0)
        return null;
     else 
        return this;
    

最后把这张图片加载到一个imageview中

logoImage.setImageBitmap(BitmapFactory.decodeByteArray( currentAccount.accImage, 
        0,currentAccount.accImage.length));

【讨论】:

insertStmt.bindBlob(3, this.accImage);用于插入图像,其中 accImage 是第一个代码块中 getLogoImage 方法返回的字节数组 我的位图为空。我得到了 byte[] 的值 能否在将 url 转换为字节数组后立即将字节数组设置为图像视图。如果您能够查看图像,那么。然后我们就可以知道数据库操作出了问题。否则,您从服务器访问图像的方式出错。 @blessenm 我正在做这样的事情。但是在 sqlite 中有更多图片/字节数组..如何避免位图内存不足错误? 游标空检查毫无意义:您已经在 moveToFirst 调用中使用过它。【参考方案2】:

在 DBAdaper 即数据库助手类中声明这样的表

 private static final String USERDETAILS=
    "create table userdetails(usersno integer primary key autoincrement,userid text not null ,username text not null,password text not null,photo BLOB,visibility text not null);";

像这样插入值,

首先将图像转换为字节[]

ByteArrayOutputStream baos = new ByteArrayOutputStream();  
Bitmap bitmap = ((BitmapDrawable)getResources().getDrawable(R.drawable.common)).getBitmap();
bitmap.compress(Bitmap.CompressFormat.PNG, 100, baos);   
byte[] photo = baos.toByteArray(); 
db.insertUserDetails(value1,value2, value3, photo,value2);

在 DEAdaper 类中

 public long insertUserDetails(String uname,String userid, String pass, byte[] photo,String visibility) 

    ContentValues initialValues = new ContentValues();
    initialValues.put("username", uname);
    initialValues.put("userid",userid);
    initialValues.put("password", pass);
    initialValues.put("photo",photo);
    initialValues.put("visibility",visibility);
    return db.insert("userdetails", null, initialValues);

按如下方式检索图像

Cursor cur=your query;
while(cur.moveToNext())

     byte[] photo=cur.getBlob(index of blob cloumn);

将字节[]转换为图像

ByteArrayInputStream imageStream = new ByteArrayInputStream(photo);
Bitmap theImage= BitmapFactory.decodeStream(imageStream);

我认为这个内容可以解决你的问题

【讨论】:

首先使用imageByteArray.length变量检查是否从光标中检索到了byte[] 检查 byte[] 长度,即 photo.lenght。如果该值大于零,那么您肯定会得到正确的位图。如果长度为零,请检查您的查询。 "System.out.println(">>>>>>>>>>> "+imageByteArray.length);"它打印什么 为什么是bitmap.compress(Bitmap.CompressFormat.PNG, 100, baos); ??如果我不想压缩我的图像怎么办? 在这里找到了我的答案***.com/questions/10191871/…【参考方案3】:

在插入()中

public void insert(String tableImg, Object object,
        ContentValues dataToInsert) 

   db.insert(tablename, null, dataToInsert);

希望对你有帮助。

【讨论】:

【参考方案4】:

对于离子项目

var imgURI = ""; var imgBBDD = ""; //sqllite 用于保存到 功能拍照() 变量选项 = 质量:75, 目的地类型:Camera.DestinationType.DATA_URL, sourceType : Camera.PictureSourceType.CAMERA, 允许编辑:真, 编码类型:Camera.EncodingType.JPEG, 目标宽度:300, 目标高度:300, popoverOptions:CameraPopoverOptions, saveToPhotoAlbum: 假 ; $cordovaCamera.getPicture(options).then(function(imageData) imgURI =“数据:图像/JPEG;base64,”+ imageData; imgBBDD = 图像数据; ,函数(错误) // 发生错误。向用户显示消息 );

现在我们将 imgBBDD 放入 SqlLite

function saveImage = function (theId, theimage) var insertQuery = "插入图像(id, image) VALUES("+theId+", '"+theimage+"');" console.log('>>>>>>>>'); DDBB.SelectQuery(插入查询) .then(函数(结果) console.log("图像已保存"); ) .catch(函数(错误) deferred.resolve(err); 返回 cb(err); );

服务器端 (php)

$request = file_get_contents("php://input"); // 获取原始数据 $dades = json_decode($request,true); // true 以数组形式返回 如果($dades=="") $数组 = 数组(); $array['error'] = -1; $array['descError'] = "获取文件时出错"; $array['logError'] = ''; 回声 json_encode($array); 出口; //再次发送图片给客户端 header('Content-Type: image/jpeg'); 回声'';

【讨论】:

【参考方案5】:
byte[] byteArray = rs.getBytes("columnname");  

Bitmap bm = BitmapFactory.decodeByteArray(byteArray, 0 ,byteArray.length);

【讨论】:

【参考方案6】:

您可能还想对 base64 进行编码和解码

    function uncompress(str:String):ByteArray 
            import mx.utils.Base64Decoder;
            var dec:Base64Decoder = new Base64Decoder();
            dec.decode(str);
            var newByteArr:ByteArray=dec.toByteArray();        
            return newByteArr;
        


    // Compress a ByteArray into a Base64 String.
    function compress(bytes:ByteArray):String  
        import mx.utils.Base64Decoder; //Transform String in a ByteArray.
        import mx.utils.Base64Encoder; //Transform ByteArray in a readable string.
        var enc:Base64Encoder = new Base64Encoder();    
        enc.encodeBytes(bytes);
        return enc.drain().split("\n").join("");
    

【讨论】:

当您可以存储字节数组时,没有充分的理由使用 base64,因为这只会增加所需的存储空间(并浪费不必要的时间编码)。 Base64 编码难以阅读。

以上是关于如何将图像存储为 Sqlite 中的 blob 以及如何检索它?的主要内容,如果未能解决你的问题,请参考以下文章

如何将 sqlite 文件中的 blob 数据读取为可读格式?

如何将图像存储在 sqlite3 数据库中

Android 从 Sqlite 数据库保存和获取图像

将数据库中的所有图像 (BLOB) 保存到文件夹(“内存不足。”)

如何调整我的模型以将上传的图像存储到我的数据库作为图像的链接而不是显示为 blob?

SQLite - 如何从 XML 文件插入 JPG 图像(使用 Delphi 2009)