为啥 getBlob() 从我的数据库中的 Blob 列中检索整数数据?
Posted
技术标签:
【中文标题】为啥 getBlob() 从我的数据库中的 Blob 列中检索整数数据?【英文标题】:Why is getBlob() retrieving Integer data from my Blob column in my database?为什么 getBlob() 从我的数据库中的 Blob 列中检索整数数据? 【发布时间】:2020-12-02 05:21:41 【问题描述】:我正在尝试将我的 SQLite 数据库中的数据显示到回收站视图。我要显示的数据是图像和文本。对于我数据库中的图像,我将图像资源转换为位图,然后转换为字节并将字节存储在我的 Blob 列中。但是,当我尝试使用 getBlob()
从列中检索字节时,我收到一个异常。
例外是android.database.sqlite.SQLiteException: unknown error (code 0 SQLITE_OK): INTEGER data in nativeGetBlob
。我知道发生此异常是因为 getBlob()
从我的 Blob 列中检索整数数据。但我不明白我将字节放入 Blob 列,那么为什么 getBlob()
检索整数数据?
我尝试使用getInt()
,但这不起作用,因为我的适配器使用BitmapFactory.decodeByteArray()
,它需要一个字节参数将我列中的字节转换为位图。
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, 0, stream);
return stream.toByteArray();
public static Bitmap getImages (byte [] image)
return BitmapFactory.decodeByteArray(image, 0, 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", null, contentValues);
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion)
db.execSQL("CREATE TABLE GROCERY_ITEMS (" + "_id INTEGER PRIMARY KEY AUTOINCREMENT, " + "NAME TEXT, " + "IMAGE_RESOURCE_ID BLOB);");
upgradeDatabase(db);
回收站视图类
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, null, null, null, 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
,表示内容实际上是图像数据本身。这种混淆本身不是问题,但表明编写代码时没有明确的方向。
您将所有图像存储到单个流中,而无法挑选出单独的图像。 如果您想将实际数据存储在数据库中,则应将每个位图编码为单独的byte[]
。
您获取生成的 mega-byte[]
的前 11 个字节,并仅将它们存储在数据库中(也存储在 11 个不同的行中)。这些字节可能只是第一个图像的标题的开头,它们本身没有任何用处。
我的建议:如果您想存储实际数据,请将convertToBytes
方法更改为采用Bitmap
参数,并为您要存储在数据库中的每个位图调用一次。
【讨论】:
【参考方案2】:听起来您查询中的第二列不是您认为的 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
是错误的数字。
【讨论】:
我已经添加了创建游标并给它一个查询的类,它在 accessDataBase() 中。不,当我查询数据库时,我将所需的列放入字符串数组中,并在数组中正确的列上调用 getBlob (1)。以上是关于为啥 getBlob() 从我的数据库中的 Blob 列中检索整数数据?的主要内容,如果未能解决你的问题,请参考以下文章
Webpack 从我的样式表中的内联 SVG 中去除标签,我不知道为啥