如何从android中的数据库中检索大型BLOB?

我像这样将图像字节保存到数据库。

byte[] imagebyte = getBytes(bitmap); boolean isuploaded = myDb.insertData("all_receipts",imagebyte); public byte[] getBytes(Bitmap bitmap) { ByteArrayOutputStream stream = new ByteArrayOutputStream(); bitmap.compress(Bitmap.CompressFormat.PNG, 70, stream); return stream.toByteArray(); } 

然后我有一个我在数据库助手类中创建的检索方法来检索所有数据。

  public ArrayList convertoArray(String tablename){ ArrayList receiptsArrayList = new ArrayList(); Model.Receipts receipt; SQLiteDatabase database = this.getReadableDatabase(); String selectQuery = "SELECT * FROM all_receipts"; if(tablename.equalsIgnoreCase("all_receipts")){ Cursor cursor = database.rawQuery(selectQuery, null); if (cursor.moveToFirst()) { do { int indexnumber = cursor.getInt(0); Bitmap image = getImage(cursor.getBlob(1)); receipt = new Model.Receipts(image,indexnumber); receiptsArrayList.add(receipt); } while (cursor.moveToNext()); } } return receiptsArrayList; } 

这与我从相机捕获的图像的缩略图工作正常。 但是当我对完整尺寸的图像使用相同的方法时,它不起作用。 我收到了错误

 Unable to start activity java.lang.IllegalStateException: Couldn't read row 0, col 0 from 

CursorWindow。 在访问数据之前,请确保正确初始化Cursor。 在

android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2255)at> android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2309)at?> android.app.ActivityThread.access $ 700(ActivityThread.java:157)at> android.app.ActivityThread $ H.handleMessage(ActivityThread.java:1289)

 From which I know that it's because that the BLOB is too big in the database. 

那么如何调用数据库中的所有图像呢?

您应该将图像的路径存储到数据库中,并使用路径访问/显示图像。


一个例子

以下是为方便起见将图像(image001.JPG到image010.JPG)存储在assets文件夹中的示例。

该示例显示图像的列表(ListView)以及1个图像并单击列表中的项目更改显示以通过存储的路径显示相应的图像。

首先是布局activity_main.xml注意包名称必须相应地改变 ): –

           

DatabaseHelper ImgDBHelper.java

 public class ImgDBHelper extends SQLiteOpenHelper { public static final String DBNAME = "myimagestore"; public static final String TBLNAME = "images"; public static final String ID_COL = "_id"; public static final String DSCR_COL = "description"; public static final String PATH_COL = "path"; //<<<<<<<< SQLiteDatabase db; ImgDBHelper(Context context) { super(context,DBNAME,null,1); db = this.getWritableDatabase(); } @Override public void onCreate(SQLiteDatabase db) { String crtsql = "CREATE TABLE IF NOT EXISTS " + TBLNAME + "(" + ID_COL + " INTEGER PRIMARY KEY, " + DSCR_COL + " TEXT," + PATH_COL + " TEXT" + ")"; db.execSQL(crtsql); } @Override public void onUpgrade(SQLiteDatabase sqLiteDatabase, int i, int i1) { } public void addImageRow(String path, String description) { Cursor csr = db.query(TBLNAME,null,PATH_COL + "=?",new String[]{path},null,null,null); // DO NOT ADD DUPLICATE IMAGES (according to path) if (csr.getCount() > 0) { csr.close(); return; } csr.close(); ContentValues cv = new ContentValues(); cv.put(DSCR_COL,description); cv.put(PATH_COL,path); db.insert(TBLNAME,null,cv); } public Cursor getAllImages() { return db.query(TBLNAME,null,null,null,null,null,null); } public String getImagePathFromID(long id) { String rv = ""; Cursor csr = db.query(TBLNAME, null, "_id=?", new String[]{Long.toString(id)}, null,null,null ); if (csr.moveToFirst()) { rv = csr.getString(csr.getColumnIndex(PATH_COL)); } csr.close(); return rv; } public boolean areImagesLoaded() { Cursor csr = db.query(TBLNAME,null,null,null,null,null,null); boolean rv = (csr.getCount() > 0); csr.close(); return rv; } } 

和Activity MainActivity.java

 public class MainActivity extends AppCompatActivity { Drawable d; // drawable for the image String imagepath = "image001.JPG"; // initial image ImgDBHelper imgdbhlpr; // DB Helper ListView imagelist; // ListView SimpleCursorAdapter sca; // ListView's Cursor adapter Cursor images; // Cursor for the ListView ImageView iv; // The ImageView to display the image @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); imagelist = (ListView) findViewById(R.id.imagelist); iv = (ImageView) findViewById(R.id.myimage); imgdbhlpr = new ImgDBHelper(this); // Load the table if there are no images if (!imgdbhlpr.areImagesLoaded()) { for (int i=1;i < 11;i++) { String path = "image" + String.format("%03d",i) + ".JPG" ; imgdbhlpr.addImageRow(path,"Image " + String.format("%03d",i)); } } // get a cursor with all of the rows images = imgdbhlpr.getAllImages(); // prepare the listview's adapter sca = new SimpleCursorAdapter(this, android.R.layout.simple_list_item_1, images, new String[]{ImgDBHelper.DSCR_COL}, new int[]{android.R.id.text1}, 0 ); // set the Listview's onItemClick listener so that clicking an // item displays the respective image imagelist.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView adapterView, View view, int i, long l) { iv.setImageDrawable(d = getImageFromAssets( imgdbhlpr.getImagePathFromID(l) )); } }); imagelist.setAdapter(sca); // set the initial image (image001.JPG) d = getImageFromAssets(imagepath); iv.setImageDrawable(d); } // routine to create a drawable according to the supplied path private Drawable getImageFromAssets(String imagepath) { Drawable drawable = null; AssetManager am = this.getAssets(); InputStream is = null; try { is = am.open(imagepath); } catch (Exception e) { e.printStackTrace(); } try { drawable = Drawable.createFromStream(is,null); } finally { try { is.close(); is = null; } catch (Exception e) { e.printStackTrace(); } } return drawable; } } 

最初运行时: –

在此处输入图像描述

然后点击Listview(image004)后: –

在此处输入图像描述

将图像存储在数据库中并不是一个好主意。而是存储指向图像的URI ..并将图像存储在文件夹中。

如果您仍想将其作为字节存储在数据库中..您可以在这里查看 。

但请记住,游标大小限制为1MB。