Android入门——数据存储之SQLite存储读取图片

引言

在Android开发中面对一些轻量级的数据库,使用最多的就是SQLite,对于其他数据类型的操作,相信很多初学者都已经知道了,但是对于图片、音乐这类的数据也是可以保存的SQLite的(虽然在实际的开发中没有人会把图片和音乐等保存到数据库,因为对于数据库来说10+KB的数据已经是很庞大的,很快就会因此造成查询性能下降)但是对于知识体系来说有必要了解下数据库保存二进制数据类型。

一、存储图片的原理概述

Android入门——数据存储之SQLite存储读取图片_第1张图片
实际上计算机的存储在物理上是都二进制的,所以文本文件与二进制文件的区别并不是物理上的,而是逻辑上的编码层次上有差异。简单来说,文本文件是基于字符编码的文件,常见的编码有ASCII编码,UNICODE编码等等;二进制文件是基于值编码的文件,你可以根据具体应用,指定某个值是什么意思(也可以看作是自定义编码)。一般文本文件基本上是定长编码的(也有非定长的编码如UTF-8)。而二进制文件可看成是变长编码的,因为是值编码嘛,多少个比特代表一个值,完全由你决定。比如说BMP文件举例子吧,其头部是较为固定长度的文件头信息,前2字节用来记录文件为BMP格式,接下来的8个字节用来记录文件长度,再接下来的4字节用来记录bmp文件头的长度。而对于一个文件流”01000000_01000001_01000010_01000011”(下划线”_”,为了增强可读性手动添加的),第一个8比特”01000000”按ASCII码来解码的话,所对应的字符是字符”A”,同理其它3个8比特可分别解码为”BCD”,即这个文件流可解释成“ABCD”,然后记事本就将这个“ABCD”显示在屏幕上。
总而言之,图片是一种比文本文件特殊的二进制文件,在SQLite提供了BLOB类型用于保存二进制数据,知道了原理之后,保存二进制就很简单了,只需二步:

  1. 把图片转为二进制(即字节数组)
  2. 把二进制文件写到数据库(如下图显示)。
    Android入门——数据存储之SQLite存储读取图片_第2张图片

二、SQLite直接存储和读取图片

其实存储图片与存储普通数据本质上没有什么不同,就是多了转为二进制的步骤,其他的都一样,没看过的可以参考Android入门——数据存储之SQLite详解与简单应用

package crazymo.com.saveimagetodb.service;

import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;

/**
 * auther: MO
 * Date: 2017/1/11
 * Time:18:33
 * Des:
 */

public class SQLiteHelper extends SQLiteOpenHelper {

    private static final String dbname="REBOT.db";
    private static final int version=1;
    private static  SQLiteHelper dbHelper;
    //也可以不指定字段的类型、长度,因为int类型也可以保存Char类型的创建学生表
    private final String createTb="CREATE TABLE User (_id INTEGER PRIMARY KEY AUTOINCREMENT,name VARCHAR2,avatar BLOB)";

    public SQLiteHelper(Context context, String name, SQLiteDatabase.CursorFactory factory, int version) {
        super(context, name, factory, version);
    }

    public SQLiteHelper(Context context){
        super(context, dbname, null, version);
    }

    public static SQLiteHelper getInstance(Context context) {

        if (dbHelper == null) { //单例模式
            dbHelper = new SQLiteHelper(context);
        }
        return dbHelper;
    }

    @Override
    public void onCreate(SQLiteDatabase db) {
        // 创建一个数据库表 User ,字段:_id、name、avatar。
        db.execSQL(createTb);
    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
    }
}

数据库操作:保存和读取图片

package crazymo.com.saveimagetodb.service;

import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;

import java.util.ArrayList;
import java.util.List;

import crazymo.com.saveimagetodb.bean.User;
import crazymo.com.saveimagetodb.util.BitmapUtil;

/**
 * auther: MO
 * Date: 2017/1/11
 * Time:18:41
 * Des:
 */

public class DBOperate {
    private SQLiteHelper dbhelper;
    private Context context;

    //要操作数据库操作实例首先得得到数据库操作实例
    public DBOperate(Context context) {
        this.context=context;
        this.dbhelper = SQLiteHelper.getInstance(context);
    }

    public void saveImage(){
        SQLiteDatabase db = dbhelper.getWritableDatabase();
        ContentValues cv=new ContentValues();
        cv.put("_id", 1);
        cv.put("avatar", bitmabToBytes(context));//图片转为二进制
        db.insert("User", null, cv);
        db.close();
    }

    public byte[] readImage(){
        SQLiteDatabase db = dbhelper.getWritableDatabase();
        Cursor cur=db.query("User", new String[]{"_id","avatar"}, null, null, null, null, null);
        byte[] imgData=null;
        if(cur.moveToNext()){
        //将Blob数据转化为字节数组
            imgData=cur.getBlob(cur.getColumnIndex("avatar"));
        }
        return imgData;
    }
//图片转为二进制数据
public byte[] bitmabToBytes(Context context){
       //将图片转化为位图
       Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(), R.mipmap.ic_launcher);
       int size = bitmap.getWidth() * bitmap.getHeight() * 4;
       //创建一个字节数组输出流,流的大小为size
       ByteArrayOutputStream baos= new ByteArrayOutputStream(size);
       try {
           //设置位图的压缩格式,质量为100%,并放入字节数组输出流中
           bitmap.compress(Bitmap.CompressFormat.PNG, 100, baos);
           //将字节数组输出流转化为字节数组byte[]
           byte[] imagedata = baos.toByteArray();
           return imagedata;
       }catch (Exception e){
       }finally {
           try {
               bitmap.recycle();
               baos.close();
           } catch (IOException e) {
               e.printStackTrace();
           }
       }
       return new byte[0];
   }

}

简单测试(代码有些不规范)

package crazymo.com.saveimagetodb;

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import butterknife.Bind;
import butterknife.OnClick;
import crazymo.com.saveimagetodb.service.DBOperate;

public class MainActivity extends AppCompatActivity {

    @Bind(R.id.save_btn)
    Button saveBtn;
    @Bind(R.id.read_btn)
    Button readBtn;
    @Bind(R.id.show_imv)
    ImageView showImv;
    private String url;
    private DBOperate dbOperate;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        butterknife.ButterKnife.bind(this);
        init();
    }
    private void init(){
        dbOperate=new DBOperate(this);
    }
    @OnClick({R.id.save_btn,R.id.read_btn})
    void onClick(View view){
        switch (view.getId()){
            case R.id.read_btn:
                readImage();
                break;
            case R.id.save_btn:
                saveImage(url);
                break;
            default:
                break;

        }
    }
    private void readImage(){

        byte[] imgData=dbOperate.readImage();
        if (imgData!=null) {
            //将字节数组转化为位图
            Bitmap imagebitmap = BitmapFactory.decodeByteArray(imgData, 0, imgData.length);
            //将位图显示为图片
            showImv.setImageBitmap(imagebitmap);
        }else {
            showImv.setBackgroundResource(android.R.drawable.menuitem_background);
        }
    }

    private void saveImage(String url){
        dbOperate.saveImage();
    }
}

Android入门——数据存储之SQLite存储读取图片_第3张图片

你可能感兴趣的:(Android,入门)