如何在android sqlite操作中将图像存储为字符串

时间:2018-04-15 20:53:40

标签: android sqlite blob

我是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;
    }

1 个答案:

答案 0 :(得分:1)

而不是尝试将位图转换为String。将位图转换为 byte [] 并存储它。

e.g。

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();
    }

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

  

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

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

您必须更改getAllProducts方法以使用Cursor 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左右,那么将它们存储在数据库中会导致检索它们时出现问题以及产生处理开销。在这种情况下,最好将图像保存为文件,并保存数据库中这些文件的路径。