【问题标题】:how to get image stored as string in android sqlite operation如何在android sqlite操作中将图像存储为字符串
【发布时间】:2018-09-25 13:35:47
【问题描述】:

我是 android 编程的初学者。我尝试编写代码以将有关产品的一些数据保存在 sqlite 数据库中。关于产品图片,我创建了一个 TEXT 类型的列 productImage。使用相机获取图像后,我从中创建了 Bitmap 对象:

Bitmap bm = (Bitmap) imageReturnedIntent.getExtras().get("data");

然后将其编码为字符串base 64:

productImageString = new ImageEncodeDecode().BitMapToString(bm);

public String BitMapToString(Bitmap bitmap){
    ByteArrayOutputStream baos=new ByteArrayOutputStream();
    bitmap.compress(Bitmap.CompressFormat.PNG,100, baos);
    byte [] b=baos.toByteArray();
    String temp=Base64.encodeToString(b, Base64.DEFAULT);
    return temp;
}

最后将其发送到产品对象中并插入到数据库中:

b.addProduct(new ProductInfo(title.getText().toString(), details.getText().toString(),
                                phone.getText().toString(), dateOfPost, price.getText().toString(), productImageString,
                                logedInUser));

虽然我将列 productImage 创建为 TEXT 类型,但编译器存储了编码的图像字符串。但是当它尝试使用 getAllProducts() 获取产品信息时,会出现以下异常:(问题的原因在这一行:productInfo.setThumbnail(cursor.getString(4));

04-15 20:41:03.601 5946-5946/com.mobileapp4u.sp.espareparts E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.mobileapp4u.sp.espareparts, PID: 5946
    java.lang.RuntimeException: Unable to start activity ComponentInfo{com.mobileapp4u.sp.espareparts/com.mobileapp4u.sp.espareparts.Main3Activity}: android.database.sqlite.SQLiteException: unknown error (code 0 SQLITE_OK): Unable to convert BLOB to string
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2892)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3027)
        at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:78)
        at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:101)
        at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:73)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1786)
        at android.os.Handler.dispatchMessage(Handler.java:106)
        at android.os.Looper.loop(Looper.java:164)
        at android.app.ActivityThread.main(ActivityThread.java:6656)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:438)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:823)
     Caused by: android.database.sqlite.SQLiteException: unknown error (code 0 SQLITE_OK): Unable to convert BLOB to string
        at android.database.CursorWindow.nativeGetString(Native Method)
        at android.database.CursorWindow.getString(CursorWindow.java:465)
        at android.database.AbstractWindowedCursor.getString(AbstractWindowedCursor.java:51)
        at com.mobileapp4u.sp.espareparts.Database.DatabaseHandler.getAllProducts(DatabaseHandler.java:229)
        at com.mobileapp4u.sp.espareparts.Main3Activity.prepareProducts(Main3Activity.java:201)
        at com.mobileapp4u.sp.espareparts.Main3Activity.onCreate(Main3Activity.java:134)
        at android.app.Activity.performCreate(Activity.java:7117)
        at android.app.Activity.performCreate(Activity.java:7108)
        at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1262)
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2867)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3027) 
        at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:78) 
        at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:101) 
        at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:73) 
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1786) 
        at android.os.Handler.dispatchMessage(Handler.java:106) 
        at android.os.Looper.loop(Looper.java:164) 
        at android.app.ActivityThread.main(ActivityThread.java:6656) 
        at java.lang.reflect.Method.invoke(Native Method) 
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:438) 
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:823) 

我该如何解决这个问题?

这是数据库代码的建表部分:

String CREATE_PRODUCTS_TABLE;
        CREATE_PRODUCTS_TABLE = "CREATE TABLE IF NOT EXISTS " + TABLE_PRODUCTS + " (" + KEY_PRODUCT_ID +
                " INTEGER PRIMARY KEY AUTOINCREMENT, "
                + KEY_PRODUCT_TITLE + " TEXT, " + KEY_PRODUCT_DETAILS + " TEXT, " + KEY_PRODUCT_DATE_OF_POST +
                " TEXT, " + KEY_PRODUCT_IMAGE + " TEXT, "
                + KEY_PRODUCT_PHONE + " TEXT, " + KEY_PRODUCT_PRICE + " INTEGER, " +
                KEY_USER_NameFK + " TEXT, " +
                "FOREIGN KEY ("+KEY_USER_NameFK+") REFERENCES "+TABLE_USERS+"("+KEY_NAME+"));";

        db.execSQL(CREATE_PRODUCTS_TABLE);

插入代码:

public void addProduct(ProductInfo productInfo)
    {
        SQLiteDatabase db = getWritableDatabase();

        ContentValues values = new ContentValues();
        values.put(KEY_PRODUCT_TITLE, productInfo.getTitle());
        values.put(KEY_PRODUCT_DETAILS, productInfo.getDescription());
        values.put(KEY_PRODUCT_DATE_OF_POST, productInfo.getDateOfPost().toString());
        values.put(KEY_PRODUCT_IMAGE, productInfo.getThumbnail());
        values.put(KEY_PRODUCT_PHONE, productInfo.getPhone());
        values.put(KEY_PRODUCT_PRICE, productInfo.getPrice());
        values.put(KEY_USER_NameFK, productInfo.getUserNameFK());

        db.insert(TABLE_PRODUCTS, null, values);
        db.close();
    }

检索代码:

public List<ProductInfo> getAllProducts()
    {
        List<ProductInfo> allProductsList = new ArrayList<ProductInfo>();
        String selectQuery = "SELECT * FROM " + TABLE_PRODUCTS;
        SQLiteDatabase db = this.getWritableDatabase();
        Cursor cursor = db.rawQuery(selectQuery, null);
        Log.d("Database Operation", "Table Created");
        // looping through all rows and adding to list
        if(cursor.moveToFirst())
        {
            do
            {
                //byte[] c = (cursor.getString(4)).getBytes();
                ProductInfo productInfo = new ProductInfo();
                productInfo.setProductId(Integer.parseInt(cursor.getString(0)));
                productInfo.setTitle(cursor.getString(1));
                productInfo.setDescription(cursor.getString(2));
                productInfo.setDateOfPost(cursor.getString(3));
                productInfo.setThumbnail(cursor.getString(4));
                productInfo.setPhone(cursor.getString(5));
                productInfo.setPrice(cursor.getString(6));
                productInfo.setUserNameFK(cursor.getString(7));

                allProductsList.add(productInfo);

            } while (cursor.moveToNext());
        }           

        db.close();
        return allProductsList;
    }

【问题讨论】:

  • productImageString = bitmapToString(bm); 应该够了
  • 数据库中的图像类型应从“TEXT”更改为“BLOB”。以下帖子详细解释了如何使用 SQL lite 存储和检索图像:Images & SQL Lite

标签: android sqlite blob


【解决方案1】:

而不是尝试将位图转换为字符串。将位图转换为 byte[] 并存储。

例如

public byte[] BitMapToString(Bitmap bitmap){
    ByteArrayOutputStream baos=new ByteArrayOutputStream();
    bitmap.compress(Bitmap.CompressFormat.PNG,100, baos);
    return b=baos.toByteArray();
}

更改您的 ProductInfo 类,以便图像的成员是 byte[] 并更改 getter 和 setter 以处理 byte[]。

插入成员,假设getThumnail 现在获取字节数组,不需要更改并且将保持为:-

public void addProduct(ProductInfo productInfo)
    {
        SQLiteDatabase db = getWritableDatabase();

        ContentValues values = new ContentValues();
        values.put(KEY_PRODUCT_TITLE, productInfo.getTitle());
        values.put(KEY_PRODUCT_DETAILS, productInfo.getDescription());
        values.put(KEY_PRODUCT_DATE_OF_POST, productInfo.getDateOfPost().toString());
        values.put(KEY_PRODUCT_IMAGE, productInfo.getThumbnail());
        values.put(KEY_PRODUCT_PHONE, productInfo.getPhone());
        values.put(KEY_PRODUCT_PRICE, productInfo.getPrice());
        values.put(KEY_USER_NameFK, productInfo.getUserNameFK());

        db.insert(TABLE_PRODUCTS, null, values);
        db.close();
    }

数据将作为 BLOB 存储在 KEY_PRODUCT_IMAGE 列中(无论该列是如何定义的(只要该列未定义为 INTEGER PRIMARY KEY 并且是因此 rowid 的别名(应用于任何值的唯一限制可以存储在任何列类型中)):-

SQLite 版本 3 数据库中的任何列,INTEGER PRIMARY 除外 KEY 列,可用于存储任何存储类的值。 Datatypes In SQLite Version 3

但是,您确实应该将列类型更改为 BLOB。

您必须更改getAllProducts 方法以使用光标getBlob 方法而不是getString 方法。这样就变成了:-

public List<ProductInfo> getAllProducts()
    {
        List<ProductInfo> allProductsList = new ArrayList<ProductInfo>();
        String selectQuery = "SELECT * FROM " + TABLE_PRODUCTS;
        SQLiteDatabase db = this.getWritableDatabase();
        Cursor cursor = db.rawQuery(selectQuery, null);
        Log.d("Database Operation", "Table Created");
        // looping through all rows and adding to list
        if(cursor.moveToFirst())
        {
            do
            {
                //byte[] c = (cursor.getString(4)).getBytes();
                ProductInfo productInfo = new ProductInfo();
                productInfo.setProductId(Integer.parseInt(cursor.getString(0)));
                productInfo.setTitle(cursor.getString(1));
                productInfo.setDescription(cursor.getString(2));
                productInfo.setDateOfPost(cursor.getString(3));
                productInfo.setThumbnail(cursor.getBlob(4)); //<<<< CHANGED
                productInfo.setPhone(cursor.getString(5));
                productInfo.setPrice(cursor.getString(6));
                productInfo.setUserNameFK(cursor.getString(7));

                allProductsList.add(productInfo);

            } while (cursor.moveToNext());
        }           
        db.close();
        return allProductsList;
    } 

然后您必须编写代码将 byte[] 转换回位图/图像。


图片存储注意事项

请注意,如果图像通常大于 100k 左右,则将它们存储在数据库中可能会导致检索它们时出现问题并产生处理开销。在这种情况下,最好将图像保存为文件,并将这些文件的路径保存在数据库中。

【讨论】:

  • 如何将 byte[] 转换回位图/图像
  • 类似ByteArrayInputStream imageStream = new ByteArrayInputStream(productInfo.getThumbnail); Bitmap yourimage = BitmapFactory.decodeStream(imageStream);
  • 我试过了。我也试过这个:Bitmap bm = BitmapFactory.decodeByteArray(img, 0, img.length);但结果位图对象总是为空
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-07-22
相关资源
最近更新 更多