为什么getBlob从数据库的Blob列中检索Integer数据?

问题描述

我正在尝试将sqlite数据库中的数据显示到回收者视图。我要显示的数据是图像和文本。对于数据库中的图像,我将图像资源转换为位图,然后转换为字节,并将字节存储在Blob列中。但是,当我尝试使用getBlob()从列中检索字节时,会收到异常。

例外是android.database.sqlite.sqliteException: unkNown error (code 0 sqlITE_OK): INTEGER data in nativeGetBlob。我知道发生这种异常是因为getBlob()从我的Blob列中检索了Integer数据。但是我不明白我将字节放入Blob列中,所以为什么getBlob()检索Integer数据?

我曾尝试使用getInt(),但由于我的适配器使用BitmapFactory.decodeByteArray(),该适配器期望使用byte参数将字节列中的字节转换为位图,因此无法正常工作。

sqlite数据库

package com.myapps.myapplication;

import android.content.ContentValues;
import android.content.Context;
import android.database.sqlite.sqliteDatabase;
import android.database.sqlite.sqliteOpenHelper;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.util.Log;

import java.io.ByteArrayOutputStream;
import java.util.ArrayList;

public class MyDatabaseHelper extends sqliteOpenHelper {

private static final String DB_NAME = "starbuzz";
private static final int DB_VERSION = 6;
private Context context;
private ArrayList <Bitmap> bitmapArray;
private byte [] byteArray;

public MyDatabaseHelper(Context context) {
    super(context,DB_NAME,null,DB_VERSION);
    this.context = context;
}

@Override
public void onCreate(sqliteDatabase db) {
    db.execsql("CREATE TABLE GROCERY_ITEMS (" + "_id INTEGER PRIMARY KEY AUTOINCREMENT," + "NAME TEXT," + "IMAGE_RESOURCE_ID BLOB);");

    upgradeDatabase(db);
}

public void upgradeDatabase (sqliteDatabase db) {
    convertToBitmap();
    byteArray = convertToByte();
    addItems(db);
}

public void convertToBitmap () {
    Bitmap faan = BitmapFactory.decodeResource(context.getResources(),R.drawable.faan);
    Bitmap milk = BitmapFactory.decodeResource (context.getResources(),R.drawable.milk);
    Bitmap egg = BitmapFactory.decodeResource (context.getResources(),R.drawable.egg);
    Bitmap toilet_tissue = BitmapFactory.decodeResource (context.getResources(),R.drawable.toilet_tissue);
    Bitmap kitchen_tissue = BitmapFactory.decodeResource (context.getResources(),R.drawable.kitchen_tissue);
    Bitmap bread = BitmapFactory.decodeResource (context.getResources(),R.drawable.bread);
    Bitmap potatoe = BitmapFactory.decodeResource (context.getResources(),R.drawable.potatoe);
    Bitmap onion = BitmapFactory.decodeResource (context.getResources(),R.drawable.onion);
    Bitmap flour = BitmapFactory.decodeResource (context.getResources(),R.drawable.flour);
    Bitmap tomatoe = BitmapFactory.decodeResource (context.getResources(),R.drawable.tomatoe);
    Bitmap corriandor = BitmapFactory.decodeResource (context.getResources(),R.drawable.corriandor);

    bitmapArray = new ArrayList <Bitmap> ();

    bitmapArray.add(faan);
    bitmapArray.add (milk);
    bitmapArray.add (egg);
    bitmapArray.add (toilet_tissue);
    bitmapArray.add (kitchen_tissue);
    bitmapArray.add (bread);
    bitmapArray.add (potatoe);
    bitmapArray.add (onion);
    bitmapArray.add (flour);
    bitmapArray.add (tomatoe);
    bitmapArray.add (corriandor);

}

public byte [] convertToByte () {

    ByteArrayOutputStream stream = new ByteArrayOutputStream ();

    for (Bitmap bitmap : bitmapArray) {
        bitmap.compress (Bitmap.CompressFormat.PNG,stream);
    }

    return stream.toByteArray();
}

public static Bitmap getimages (byte [] image) {
    return BitmapFactory.decodeByteArray(image,image.length);
}

public void addItems (sqliteDatabase db) {

    byte faan = byteArray [0];
    byte milk = byteArray [1];
    byte egg = byteArray [2];
    byte toilet_tissue = byteArray [3];
    byte kitchen_tissue = byteArray [4];
    byte bread = byteArray [5];
    byte potatoe = byteArray [6];
    byte onion = byteArray [7];
    byte flour = byteArray [8];
    byte tomatoe = byteArray [9];
    byte corriandor = byteArray [10];

    insertItems (db,"Faan",faan);
    insertItems (db,"Milk",milk);
    insertItems (db,"Egg",egg);
    insertItems (db,"Toilet Tissue",toilet_tissue);
    insertItems (db,"Kitchen Tissue",kitchen_tissue);
    insertItems (db,"Bread",bread);
    insertItems (db,"Potatoe",potatoe);
    insertItems (db,"Onion",onion);
    insertItems (db,"Flour",flour);
    insertItems (db,"Tomatoe",tomatoe);
    insertItems (db,"Corriandor",corriandor);

}

public void insertItems (sqliteDatabase db,String name,byte image) {
    ContentValues contentValues = new ContentValues();
    contentValues.put ("NAME",name);
    contentValues.put ("IMAGE_RESOURCE_ID",image);

    db.insert ("GROCERY_ITEMS",contentValues);
}

@Override
public void onUpgrade(sqliteDatabase db,int oldVersion,int newVersion) {
    db.execsql("CREATE TABLE GROCERY_ITEMS (" + "_id INTEGER PRIMARY KEY AUTOINCREMENT," + "IMAGE_RESOURCE_ID BLOB);");

    upgradeDatabase(db);
}
}

Recycler View类

package com.myapps.myapplication;

import android.database.Cursor;
import android.database.sqlite.sqliteDatabase;
import android.database.sqlite.sqliteException;
import android.os.Bundle;
import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.GridLayoutManager;
import androidx.recyclerview.widget.RecyclerView;

public class grocery_item extends AppCompatActivity {

sqliteDatabase db;
Cursor cursor;

protected void onCreate (Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.item_grocery);

    accessDataBase();

    RecyclerView groceryRecycler = (RecyclerView) findViewById(R.id.grocery_recycler_view);

    captionedImagesAdapter adapter = new captionedImagesAdapter (this,cursor);
    GridLayoutManager layoutManager = new GridLayoutManager(this,2,GridLayoutManager.VERTICAL,false);
    groceryRecycler.setLayoutManager(layoutManager);
    groceryRecycler.setAdapter (adapter);
}

public void accessDataBase () {
    MyDatabaseHelper databaseHelper = new MyDatabaseHelper(this);

    try {

        db = databaseHelper.getReadableDatabase();

        cursor = db.query ("GROCERY_ITEMS",new String[] {"NAME","IMAGE_RESOURCE_ID"},null);

    } catch (sqliteException e) {
        e.printstacktrace();
    }
}
}

回收站视图适配器:

package com.myapps.myapplication;

import android.content.Context;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.recyclerview.widget.RecyclerView;
import androidx.cardview.widget.CardView;

public class captionedImagesAdapter extends RecyclerView.Adapter <captionedImagesAdapter.ViewHolder> {

private Context context;
private Cursor cursor;

public captionedImagesAdapter (Context context,Cursor cursor) {
    this.context = context;
    this.cursor = cursor;
}

public captionedImagesAdapter.ViewHolder onCreateViewHolder (ViewGroup parent,int viewType) {
    LayoutInflater inflater = LayoutInflater.from(context);
    CardView cv = (CardView) inflater.inflate(R.layout.card_view,parent,false);

    return new ViewHolder (cv);
}

public void onBindViewHolder(ViewHolder holder,int position) {
    if (!cursor.movetoPosition(position)) {
        return;
    }

    String info_text = cursor.getString (0);
    byte [] info_image = cursor.getBlob(1);

    Bitmap bitmap = MyDatabaseHelper.getimages(info_image);

    holder.textView.setText(info_text);
    holder.imageView.setimageBitmap(bitmap);
}

public int getItemCount() {
    return cursor.getCount();
}

public static class ViewHolder extends RecyclerView.ViewHolder {
    private ImageView imageView;
    private TextView textView;

    public ViewHolder(CardView view) {
        super(view);
        imageView = view.findViewById(R.id.info_image);
        textView = view.findViewById(R.id.info_text);
    }
}
}

例外:

android.database.sqlite.sqliteException: unkNown error (code 0 sqlITE_OK): INTEGER data in nativeGetBlob 
    at android.database.CursorWindow.nativeGetBlob(Native Method)
    at android.database.CursorWindow.getBlob(CursorWindow.java:434)
    at android.database.AbstractwindowedCursor.getBlob(AbstractwindowedCursor.java:47)
    at com.myapps.myapplication.captionedImagesAdapter.onBindViewHolder(captionedImagesAdapter.java:43)
    at com.myapps.myapplication.captionedImagesAdapter.onBindViewHolder(captionedImagesAdapter.java:14)
    at androidx.recyclerview.widget.RecyclerView$Adapter.onBindViewHolder(RecyclerView.java:7178)
    at androidx.recyclerview.widget.RecyclerView$Adapter.bindViewHolder(RecyclerView.java:7258)
    at androidx.recyclerview.widget.RecyclerView$Recycler.tryBindViewHolderByDeadline(RecyclerView.java:6125)
    at androidx.recyclerview.widget.RecyclerView$Recycler.tryGetViewHolderForPositionByDeadline(RecyclerView.java:6391)
    at androidx.recyclerview.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:6231)
    at androidx.recyclerview.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:6227)
    at androidx.recyclerview.widget.linearlayoutmanager$LayoutState.next(linearlayoutmanager.java:2330)
    at androidx.recyclerview.widget.GridLayoutManager.layoutChunk(GridLayoutManager.java:572)
    at androidx.recyclerview.widget.linearlayoutmanager.fill(linearlayoutmanager.java:1591)
    at androidx.recyclerview.widget.linearlayoutmanager.onLayoutChildren(linearlayoutmanager.java:668)
    at androidx.recyclerview.widget.GridLayoutManager.onLayoutChildren(GridLayoutManager.java:170)
    at androidx.recyclerview.widget.RecyclerView.dispatchLayoutStep2(RecyclerView.java:4230)
    at androidx.recyclerview.widget.RecyclerView.dispatchLayout(RecyclerView.java:3941)
    at androidx.recyclerview.widget.RecyclerView.onLayout(RecyclerView.java:4499)
    at android.view.View.layout(View.java:22085)
    at android.view.ViewGroup.layout(ViewGroup.java:6290)
    at android.widget.FrameLayout.layoutChildren(FrameLayout.java:332)
    at android.widget.FrameLayout.onLayout(FrameLayout.java:270)
    at android.view.View.layout(View.java:22085)
    at android.view.ViewGroup.layout(ViewGroup.java:6290)
    at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1829)
    at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1673)
    at android.widget.LinearLayout.onLayout(LinearLayout.java:1582)
    at android.view.View.layout(View.java:22085)
    at android.view.ViewGroup.layout(ViewGroup.java:6290)
    at android.widget.FrameLayout.layoutChildren(FrameLayout.java:332)
    at android.widget.FrameLayout.onLayout(FrameLayout.java:270)
    at android.view.View.layout(View.java:22085)
    at android.view.ViewGroup.layout(ViewGroup.java:6290)
    at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1829)
    at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1673)
    at android.widget.LinearLayout.onLayout(LinearLayout.java:1582)
    at android.view.View.layout(View.java:22085)
    at android.view.ViewGroup.layout(ViewGroup.java:6290)
    at android.widget.FrameLayout.layoutChildren(FrameLayout.java:332)
    at android.widget.FrameLayout.onLayout(FrameLayout.java:270)
    at com.android.internal.policy.DecorView.onLayout(DecorView.java:786)
    at android.view.View.layout(View.java:22085)
    at android.view.ViewGroup.layout(ViewGroup.java:6290)
    at android.view.ViewRootImpl.performlayout(ViewRootImpl.java:3333)
    at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:2810)
    at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1930)
    at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:7988)
    at android.view.Choreographer$CallbackRecord.run(Choreographer.java:1154)
    at android.view.Choreographer.doCallbacks(Choreographer.java:977)
    at android.view.Choreographer.doFrame(Choreographer.java:893)
    at android.view.Choreographer$FrameHandler.handleMessage(Choreographer.java:1082)
    2020-08-12 13:34:17.755 14399-14399/com.myapps.myapplication E/AndroidRuntime:     at 
    android.os.Handler.dispatchMessage(Handler.java:107)
    at android.os.Looper.loop(Looper.java:214)
    at android.app.ActivityThread.main(ActivityThread.java:7682)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:516)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:950)

解决方法

从哪里开始?

  1. 您为列IMAGE_RESOURCE_ID命名,这表明您在其中存储了某种识别码,但类型为BLOB,表明内容实际上是图像数据本身。这种混乱本身并不是问题,但是表明编写代码时并没有明确的方向。
  2. 您将所有图片存储到单个流中,而无法挑选出单独的图片。 如果您想将实际数据存储在数据库中,则应将每个位图编码为单独的byte[]
  3. 您将从结果mega-byte[]的前11个字节中取出,并仅将其存储在数据库中(也存储在11个不同的行中)。这些字节可能只是第一张图片的标题的开头,它们本身没有任何有用的含义。

我的建议:如果您要存储实际数据,请更改convertToBytes方法以使用Bitmap参数,并为要存储的每个位图调用一次在数据库中。

,

听起来您查询中的第二列不是您认为的blob;您正在使用.getBlob(1)访问它,这意味着:取第二列的值并将其作为blob给出给我,错误似乎表明:..不能做,它不是blob,而是整数。

您还没有将您的粘贴到您的AbstractWindowedCursor对象的位置;它是传递到captionedImagesAdapter类的构造函数中的游标。这背后是什么查询?我敢打赌它是SELECT foo,bar,baz FROM something,其中bar实际上不是blob值。例如,如果您做了SELECT * FROM GROCERY_ITEMS,则第一列(例如.getInt(0))是id列,第二列是名称(文本),第三列是blob。如果尝试在此上运行.getBlob(1),最终将得到与该错误类似的错误,因为1是错误的数字。