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

Posted

技术标签:

【中文标题】如何将图像存储在 SQLite 数据库中【英文标题】:How to store image in SQLite database 【发布时间】:2012-03-10 14:08:35 【问题描述】:

在我的应用程序中,我正在从图库上传一张图片,我想将此图片存储在 SQLite 数据库中。如何在数据库中存储位图?我正在将位图转换为字符串并将其保存在数据库中。从数据库中检索它时,我无法将该字符串分配给 ImageView,因为它是一个字符串。

Imageupload12 .java:

     public class Imageupload12 extends Activity 
      Button buttonLoadImage;
      ImageView targetImage;
      int i = 0;
      Database database = new Database(this);
      String i1;
      String img;
      @Override
      public void onCreate(Bundle savedInstanceState) 
       super.onCreate(savedInstanceState);
       setContentView(R.layout.main5);
       buttonLoadImage = (Button) findViewById(R.id.loadimage);
       targetImage = (ImageView) findViewById(R.id.targetimage);
    
    
       Bundle b = getIntent().getExtras();
       if (b != null) 
        img = b.getString("image");
        targetImage2.setImageURI("image");
        //i am getting error as i cant assign string to imageview.
    
       
    
       buttonLoadImage.setOnClickListener(new Button.OnClickListener() 
    
        public void onClick(View arg0) 
         // TODO Auto-generated method stub
         Intent intent = new Intent(Intent.ACTION_PICK,
          android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
         Log.i("photo", "" + intent);
         startActivityForResult(intent, i);
         i = i + 1;
        
       );
    
      
    
      @Override
      protected void onActivityResult(int requestCode, int resultCode, Intent data) 
    
       // TODO Auto-generated method stub
       super.onActivityResult(requestCode, resultCode, data);
       switch (requestCode) 
    
        case 0:
         if (resultCode == RESULT_OK) 
          Uri targetUri = data.getData();
          //             textTargetUri.setText(targetUri.toString());
          Bitmap bitmap;
          try 
           bitmap = BitmapFactory.decodeStream(getContentResolver().openInputStream(targetUri));
           targetImage.setImageBitmap(bitmap);
    
           i1 = bitmap.toString();
           Log.i("firstimage........", "" + i1);
           targetImage.setVisibility(0);
    
           SQLiteDatabase db = database.getWritableDatabase();
           db.execSQL("INSERT INTO UPLOAD VALUES('" + i1 + "');");
    
           catch (FileNotFoundException e) 
           // TODO Auto-generated catch block
           e.printStackTrace();
          
         
         break;
    
    
    
       
    
      
     

Image.class:

    public class Image extends Activity 
     Database database = new Database(this);
     static EfficientAdapter adapter, adapter1;
     static ListView lv1;
    
     static SQLiteDatabase db;
     static EfficientAdapter adp;
     static Cursor c1;
    
     static Vector < String > IMAGE = new Vector < String > ();
    
     @Override
     public void onCreate(Bundle savedInstanceState) 
      super.onCreate(savedInstanceState);
      setContentView(R.layout.main);
    
      db = database.getReadableDatabase();
      c1 = db.rawQuery("select * from UPLOAD;", null);
    
      if (c1.moveToFirst()) 
    
       do 
        IMAGE.add(c1.getString(0).toString());
    
        while (c1.moveToNext());
    
       c1.close();
      
    
      lv1 = (ListView) findViewById(R.id.List);
    
      adapter = new EfficientAdapter(this);
    
    
      lv1.setAdapter(adapter);
    
      ImageView add = (ImageView) findViewById(R.id.imv1a);
    
    
    
      add.setOnClickListener(new OnClickListener() 
    
       @Override
       public void onClick(View v) 
        // TODO Auto-generated method stub
        IMAGE.clear();
    
        Intent i = new Intent(Image.this, Imageupload12.class);
        startActivity(i);
    
    
       
      );
    
    
     
    
    
    
     private static class EfficientAdapter extends BaseAdapter 
    
    
      //        protected  final Context Context = null;
      protected LayoutInflater mLayoutInflater;
      AlertDialog.Builder aBuilder;
      public EfficientAdapter(Context context) 
       // TODO Auto-generated constructor stub
       mLayoutInflater = LayoutInflater.from(context);
      
    
      @Override
      public int getCount() 
       // TODO Auto-generated method stub
    
       return IMAGE.size();
      
    
      @Override
      public Object getItem(int position) 
       // TODO Auto-generated method stub
       return position;
      
    
      @Override
      public long getItemId(int position) 
       // TODO Auto-generated method stub
       return position;
      
    
      @Override
      public View getView(final int position, View convertView, ViewGroup parent) 
       // TODO Auto-generated method stub
    
       final ViewHolder mVHolder;
       if (convertView == null) 
        convertView = mLayoutInflater.inflate(R.layout.pjtlistdetails, parent, false);
    
        mVHolder = new ViewHolder();
    
        mVHolder.t1 = (TextView) convertView.findViewById(R.id.pjtdetails);
        mVHolder.time = (TextView) convertView.findViewById(R.id.name);
    
    
        mVHolder.imv = (ImageButton) convertView.findViewById(R.id.editic);
        mVHolder.imvd = (ImageView) convertView.findViewById(R.id.delete);
        mVHolder.imvf = (ImageView) convertView.findViewById(R.id.fwd);
    
    
    
    
    
        mVHolder.imv.setOnClickListener(new View.OnClickListener() 
         @Override
         public void onClick(View v) 
    
    
    
          String img = IMAGE.elementAt(position);
          Log.i("image...", "" + img);
    
          Context ctx = v.getContext();
          Intent myIntent = new Intent();
          ctx = v.getContext();
          myIntent.setClass(ctx, Imageupload12.class);
          myIntent.putExtra("image", img);
    
          ctx.startActivity(myIntent);
    
          IMAGE.clear();
    
         
        );
        static class ViewHolder 
    
         ImageButton imv;
         ImageView imvd, imvf;
        
       
      
     
    

【问题讨论】:

请参考此链接。肯定你会明白的。 ***.com/questions/11790104/… 【参考方案1】:

您必须使用“blob”来存储图像。

例如:将图像存储到数据库中:

public void insertImg(int id , Bitmap img )    


    byte[] data = getBitmapAsByteArray(img); // this is a function

    insertStatement_logo.bindLong(1, id);       
    insertStatement_logo.bindBlob(2, data);

    insertStatement_logo.executeInsert();
    insertStatement_logo.clearBindings() ;



 public static byte[] getBitmapAsByteArray(Bitmap bitmap) 
    ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
    bitmap.compress(CompressFormat.PNG, 0, outputStream);       
    return outputStream.toByteArray();

从数据库中检索图像:

public Bitmap getImage(int i)

    String qu = "select img  from table where feedid=" + i ;
    Cursor cur = db.rawQuery(qu, null);

    if (cur.moveToFirst())
        byte[] imgByte = cur.getBlob(0);
        cur.close();
        return BitmapFactory.decodeByteArray(imgByte, 0, imgByte.length);
    
    if (cur != null && !cur.isClosed()) 
        cur.close();
           

    return null;
 

【讨论】:

这里您在数据库中插入特定图像,但我需要从图库中选择图像,然后我需要将该图像插入数据库并检索该图像。 要从图库中选择图像,请检查此问题。 ***.com/questions/2507898/… 使用此编码,您可以将图库图像加载到位图中。之后将该位图存储到数据库中,就像我在这里展示的那样。【参考方案2】:

使用 blob 将图像存储在 sqlite 数据库中。下面是一个关于如何使用 blob 的示例。

设置数据库

CREATE TABLE " + DB_TABLE + "("+ 
                   KEY_NAME + " TEXT," + 
                   KEY_IMAGE + " BLOB);";

插入数据库:

public void addEntry( String name, byte[] image) throws SQLiteException
    ContentValues cv = new  ContentValues();
    cv.put(KEY_NAME,    name);
    cv.put(KEY_IMAGE,   image);
    database.insert( DB_TABLE, null, cv );

检索数据

 byte[] image = cursor.getBlob(1);

注意:

    在插入数据库之前,您需要先将您的位图图像转换为字节数组,然后使用数据库查询应用它。 从数据库中检索时,您肯定有一个字节数组的图像,您需要做的就是将字节数组转换回原始图像。所以,你必须使用 BitmapFactory 来解码。

下面是一个实用类,希望对你有帮助:

public class DbBitmapUtility 

    // convert from bitmap to byte array
    public static byte[] getBytes(Bitmap bitmap) 
        ByteArrayOutputStream stream = new ByteArrayOutputStream();
        bitmap.compress(CompressFormat.PNG, 0, stream);
        return stream.toByteArray();
    

    // convert from byte array to bitmap
    public static Bitmap getImage(byte[] image) 
        return BitmapFactory.decodeByteArray(image, 0, image.length);
    

【讨论】:

很好,但你应该在getBytes(Bitmap bitmap)中处理流 不要忘记在return stream.toByteArray(); 之前致电stream.close 以避免泄漏。 @LazyNinja 如何将选中的图像传入字节数组***.com/questions/63610127/… @Karthickyuvan 我看到了你的问题。为什么不传递图像而不是传递 COLUMN_ID?由于您可以从任何地方访问数据库,因此只需使用 columnId 检索图像。希望对您有所帮助。 我无法插入图片!【参考方案3】:

要将任何图像存储在 sqlite 数据库中,您需要将该图像存储在字节数组而不是字符串中。将该图像转换为字节数组并将该字节 [] 存储到 DB。在检索该图像时,您将获得字节 [] 将该字节 [] 转换为位图,您将通过该位图获得原始图像。

【讨论】:

【参考方案4】:

我认为将图像存储到 SQLLite 数据库的最佳方法是使用 Base 64 算法。它将图像转换为纯文本并再次返回。您可以在以下位置下载完整的示例 Android 项目:www.developersfound.com/Base64FromStream.zip。该程序不存储图像,但它确实将图像从图像转换为文本并再次转换回来。 上面的下载链接包含下面的 Kotlin 代码版本。

这是课程:

package com.example.TestProject;

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.util.Base64;
import android.util.Log;

import java.io.*;
import java.net.URL;
import java.net.URLConnection;
import java.nio.channels.FileChannel;

public class Base64CODEC 
    private int IO_BUFFER_SIZE = 64;
    //private int IO_BUFFER_SIZE = 8192;
    private URL urlObject = null;
    private URLConnection myConn = null;
    ByteArrayOutputStream os = null;

    public void Base64CODEC() 

    public Bitmap Base64ImageFromURL(String url) 
        Bitmap bitmap = null;
        InputStream in = null;
        BufferedOutputStream out = null;

        try 
            urlObject = new URL(url);
            myConn = urlObject.openConnection();
            in = myConn.getInputStream();

            final ByteArrayOutputStream dataStream = new ByteArrayOutputStream();
            out = new BufferedOutputStream(dataStream, IO_BUFFER_SIZE);

            copyCompletely(in, out);

            final byte[] data = dataStream.toByteArray();
            BitmapFactory.Options options = new BitmapFactory.Options();

            bitmap = BitmapFactory.decodeByteArray(data, 0, data.length, options);
         catch (IOException e) 
            Log.e("TAG", "Could not load Bitmap from: " + url);
         finally 
            //closeStream(in);
            try 
                in.close();
             catch (IOException e) 
                e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
            
            //closeStream(out);
            try 
                out.close();
             catch (IOException e) 
                e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
            
        

        return bitmap;
    

    private void copyCompletely(InputStream input, OutputStream output) throws IOException 
        // if both are file streams, use channel IO
        if ((output instanceof FileOutputStream) && (input instanceof FileInputStream)) 
            try 
                FileChannel target = ((FileOutputStream) output).getChannel();
                FileChannel source = ((FileInputStream) input).getChannel();

                source.transferTo(0, Integer.MAX_VALUE, target);

                source.close();
                target.close();

                return;
             catch (Exception e)  /* failover to byte stream version */
            
        

        byte[] buf = new byte[8192];
        while (true) 
            int length = input.read(buf);
            if (length < 0)
                break;
            output.write(buf, 0, length);
        

        try 
            input.close();
         catch (IOException ignore) 
        
        try 
            output.close();
         catch (IOException ignore) 
    

    public String convertToBase64(Bitmap bitmap) 
        ByteArrayOutputStream os = new ByteArrayOutputStream();
        bitmap.compress(Bitmap.CompressFormat.PNG,100,os);
        byte[] byteArray = os.toByteArray();
        return Base64.encodeToString(byteArray, 0);
    

    public Bitmap convertToBitmap(String base64String) 
        byte[] decodedString = Base64.decode(base64String, Base64.DEFAULT);
        Bitmap bitmapResult = BitmapFactory.decodeByteArray(decodedString, 0, decodedString.length);
        return bitmapResult;
    


这是使用该类的主要活动:

package com.example.TestProject;

import android.app.Activity;
import android.graphics.Bitmap;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.View;
import android.widget.ImageView;

public class MainActivity extends Activity implements Runnable 

    private Thread thread = null;
    private Bitmap bitmap = null;
    private Base64CODEC base64CODEC = null;
    private ImageView imgViewSource = null;
    private ImageView imgViewDestination = null;
    private boolean isSourceImageVisible = false;

    @Override
    public void onCreate(Bundle savedInstanceState) 
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
    

    public void CmdLoadImage_Click(View view) 
        try 
            if(isSourceImageVisible == true) 
                imgViewSource.setImageBitmap(null);
                imgViewDestination.setImageBitmap(null);
                isSourceImageVisible = false;
            
            else 
                base64CODEC = new Base64CODEC();
                thread = new Thread(this);
                thread.start();
            
        
        catch (NullPointerException e) 

    

    public void CmdEncodeImage_Click(View view) 
        Base64CODEC base64CODEC = new Base64CODEC();
        try 
            String base64String = base64CODEC.convertToBase64(bitmap);
            imgViewDestination = (ImageView) findViewById(R.id.imgViewDestination);
            Bitmap imgViewDestinationBitmap = base64CODEC.convertToBitmap(base64String);
            imgViewDestination.setImageBitmap(imgViewDestinationBitmap);
        
        catch (NullPointerException e) 
            //
        
    

    @Override
    public void run() 
        bitmap = base64CODEC.Base64ImageFromURL("http://developersfound.com/me.png");
        handler.sendEmptyMessage(0);
    

    private Handler handler = new Handler() 
        @Override
        public void handleMessage(Message msg) 
            imgViewSource = (ImageView) findViewById(R.id.imgViewSource);
            imgViewSource.setImageBitmap(bitmap);
            isSourceImageVisible = true;
            thread = null;
        
    ;


【讨论】:

哦,不!你会膨胀你的数据库!你说你最相信,你有理由相信吗? 我们应该在DB android-存储位图作为blob还是以字符串格式存储什么?【参考方案5】:

我有两件事需要注意。 如何存储图库中的图像以及如何存储 uri 中的图像,例如 (www.example.com/myimage.png)

如何存储图库中的图像

图像是从 Uri 数据类型的图库中检索的。为了将图像存储到 android SQLite 数据库,您需要将图像 uri 转换为位图,然后转换为二进制字符,即 bytes[] 序列。然后将表列数据类型设置为 BLOB 数据类型。从 DB 中检索图像后,将 byte[] 数据类型转换为位图,以便将其设置为 imageview。

如何从 uri 中存储图像。

请注意,您可以将图像作为 uri 字符串存储在数据库中,但只能将图像 uri 来自网站。将 uri 转换为字符串并将其插入到您的数据库中。将您的图像 uri 作为字符串检索并转换为 uri 数据类型,以便将其设置为 imageview。

你可以试试这个帖子的工作程序和source code how to store images in Sqlite database and display in listview

【讨论】:

要从图库中存储图像,使用读取权限选择图像,然后将该图像转换为位图图像,然后转换为字节数组以将其存储在数据库中。【参考方案6】:

不要忘记在 Manifest 文件中写入用户权限代码

    protected void onCreate(Bundle savedInstanceState) 
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            CameraActivity = this;

            imageView = (ImageView) findViewById(R.id.image_view);
            database = new ImageDatabase(this);

            //Set OnClick Listener to button view
            captureImage = (Button) findViewById(R.id.capture_image);
            captureImage.setOnClickListener(new View.OnClickListener() 
                @Override
                public void onClick(View v) 


                    Intent cameraIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
                    startActivityForResult(cameraIntent, CAMERA_REQUEST);
                
            );


        

        @Override
        public void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) 
            if (requestCode == CAMERA_REQUEST && resultCode == Activity.RESULT_OK) 

                theImage = (Bitmap) data.getExtras().get("data");

                ByteArrayOutputStream stream = new ByteArrayOutputStream();
                theImage.compress(Bitmap.CompressFormat.PNG, 100, stream);
                byte[] byteArray = stream.toByteArray();

                SQLiteDatabase db = database.getWritableDatabase();
                ContentValues values = new ContentValues();
                values.put(ImageDatabase.KEY_IMG_URL, byteArray);
                db.insert(ImageDatabase.TABLE_NAME, null, values);
                db.close();
                Bitmap b = getTheImage();
                imageView.setImageBitmap(b);

            
        

       public Bitmap getTheImage()

            SQLiteDatabase db = database.getReadableDatabase();
            Cursor cursor = (Cursor) db.rawQuery(" SELECT * FROM "+ImageDatabase.TABLE_NAME,null,null);
            if (cursor.moveToFirst())
                byte[] imgByte =  cursor.getBlob(cursor.getColumnIndex(ImageDatabase.KEY_IMG_URL));
                cursor.close();
                return BitmapFactory.decodeByteArray(imgByte,0,imgByte.length);
            
           if (cursor != null && !cursor.isClosed()) 
               cursor.close();
           

           return null;
        
    

数据库类

class ImageDatabase extends SQLiteOpenHelper 
    public Context context;
    public static final String DATABASE_NAME = "dataManager";

    public static final int DATABASE_VERSION = 1;
    public static final String TABLE_NAME = "data";
    public static final String KEY_ID = "id";
    public static final String KEY_IMG_URL = "ImgFavourite";

    public ImageDatabase(Context context) 
        super(context, DATABASE_NAME, null, DATABASE_VERSION);
        this.context = context;
        //Toast.makeText(context, "Constructor called", Toast.LENGTH_LONG).show();
    

    public static final String CREATE_TABLE = "CREATE TABLE " + TABLE_NAME + "(" + KEY_ID +
            " INTEGER PRIMARY KEY AUTOINCREMENT," + KEY_IMG_URL + " BLOB " + ")";
    public static final String DROP_TABLE = "DROP TABLE IF EXISTS " + TABLE_NAME + "";

    @Override
    public void onCreate(SQLiteDatabase db) 
        db.execSQL(CREATE_TABLE);
    

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) 
        db.execSQL(DROP_TABLE);
        onCreate(db);
    

    public void deleteEntry(long row) 
        SQLiteDatabase sqLiteDatabase = getWritableDatabase();
        sqLiteDatabase.delete(TABLE_NAME, KEY_ID + "=" + row, null);
    


【讨论】:

以上是关于如何将图像存储在 SQLite 数据库中的主要内容,如果未能解决你的问题,请参考以下文章

如何将图像存储在 iPhone 的 sqlite 数据库中? [关闭]

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

如何使用 iphone 中的核心数据将图像存储到 sqlite? [复制]

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

图像不存储在 sqlite

Android:我需要拍照并将其存储在 sqlite 数据库中,然后将其填充到回收站视图中