Следующая демонстрация сохранит изображение либо в базе данных, либо во внутренней памяти приложения.
Если размер изображения <256 КБ (согласно <code>public static final int MAX_IMAGESIZETOSTORE = 1024 * 256;), он будет сохранен в БД.и могут быть извлечены из базы данных.
Если изображение имеет размер 256 КБ или более (с ограничением в 16 МБ для демонстрации согласно public static final int MAXIMAGEBUFFER = 1024 * 1024 * 16;
), то оно будет храниться в каталоге Files / myimagestores приложения (myimagestores)каталог, создаваемый демо), а путь к изображению сохраняется в базе данных.
Демо, вместо получения изображений с камеры, получает изображения из папки активов (5 использовались для демонстрации).
Код не будет работать должным образом, если изображения не находятся в папке ресурсов и если они не определены с соответствующими именами согласно : -
String[] imagesToGet = new String[]{"sample001.jpg","sample002.jpg","sample003.jpg","sample004.jpg","sample005.jpg"};
Код
SQLiteHelper.java
- Это в основном ваш помощник с измененным insertData методом, который является
: -
public long insertData(String name, String stok, String jual, byte[] image) {
SQLiteDatabase db = this.getWritableDatabase();
ContentValues cv = new ContentValues();
cv.put(RECORD_COL_NAME,name);
cv.put(RECORD_COL_STOK,stok);
cv.put(RECORD_COL_JUAL,jual);
if (image.length > 0 && image.length < MAX_IMAGESIZETOSTORE) {
cv.put(RECORD_COL_IMAGE,image);
} else {
cv.put(RECORD_COL_IMAGEPATH,StoreImage.storeImage(mContext,image,name));
}
return db.insert(TBLNAME_RECORD,null,cv);
}
На уровне класса объявлены следующие константы: -
public static final int MAX_IMAGESIZETOSTORE = 1024 * 256;
public static final String DBNAME = "mydb";
public static final int DBVERSION = 1;
public static final String TBLNAME_RECORD = "record";
public static final String RECORD_COl_ID = BaseColumns._ID;
public static final String RECORD_COL_NAME = "name";
public static final String RECORD_COL_STOK = "stok";
public static final String RECORD_COL_JUAL = "jual";
public static final String RECORD_COL_IMAGE = "image";
public static final String RECORD_COL_IMAGEPATH = "imagepath";
- , как видно из дополнительного столбца, imagepath был добавлен для хранения пути к изображению(null, если изображение хранится в БД, и наоборот, если изображение хранится не в БД, а в виде файла, тогда столбец image будет иметь значение null).
StoreImage.java is
: -
public class StoreImage {
public static final String IMAGESTOREDIRECTORY = "myimagestore";
public static String storeImage(Context context, byte[] image, String imagename) {
File mFilesDirectory = context.getFilesDir();
File mImageStoreDirectory = new File(mFilesDirectory.getPath() + File.separator + IMAGESTOREDIRECTORY);
if (!mImageStoreDirectory.exists()) {
mImageStoreDirectory.mkdirs();
}
File mImageStore = new File(mImageStoreDirectory.getPath() + File.separator + imagename);
OutputStream os;
try {
os = new FileOutputStream(mImageStore);
os.write(image);
os.flush();
os.close();
} catch (IOException e) {
e.printStackTrace();
}
return mImageStore.getPath();
}
}
Как видно из вышеизложенного, метод storeImage метода * 1047Класс * StoreImage хранит изображение (байт [], переданный методу insertData класса SQliteHelper .
Как можно видеть вышепри необходимости создаст каталог myimagestore .
MainActivity.java is
: -
public class MainActivity extends AppCompatActivity {
public static final int MAXIMAGEBUFFER = 1024 * 1024 * 16;
SQLiteHelper mDBHlpr;
// The demo images copied into the assets folder
String[] imagesToGet = new String[]{"sample001.jpg","sample002.jpg","sample003.jpg","sample004.jpg","sample005.jpg"};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mDBHlpr = new SQLiteHelper(this);
for (String s: imagesToGet) {
mDBHlpr.insertData(s,"stock for " + s,"jual for " + s,getImage(s));
}
Cursor csr = mDBHlpr.getData("SELECT * FROM RECORD;");
DatabaseUtils.dumpCursor(csr);
csr.close();
}
//Get a demo image from the assets folder
private byte[] getImage(String name) {
byte[] buffer = new byte[0];
try {
AssetFileDescriptor afd = this.getAssets().openFd(name);
long fsz = afd.getLength();
if (fsz < MAXIMAGEBUFFER) {
InputStream is = this.getAssets().open(name);
buffer = new byte[(int) fsz];
is.read(buffer, 0, (int) fsz);
}
} catch (IOException e) {
e.printStackTrace();
}
return buffer;
}
}
getImage Метод, основная часть действия, извлекает изображение из папки активов (демонстрационные изображения).
5 демонстрационных изображений обрабатываются в цикле и добавляются в базу данных через insertData Метод.
После вставки все данные извлекаются в Курсор, и Курсор сбрасывается (записывается в журнал).
Пример выполнения: -
С изображениямископированы в папку ресурсов согласно: -
И приложение запустится, тогда журнал содержит: -
06-01 08:59:14.828 7728-7728/? I/System.out: >>>>> Dumping cursor android.database.sqlite.SQLiteCursor@cd7f7ce
06-01 08:59:14.828 7728-7728/? I/System.out: 0 {
06-01 08:59:14.828 7728-7728/? I/System.out: _id=1
06-01 08:59:14.828 7728-7728/? I/System.out: name=sample001.jpg
06-01 08:59:14.828 7728-7728/? I/System.out: stok=stock for sample001.jpg
06-01 08:59:14.828 7728-7728/? I/System.out: jual=jual for sample001.jpg
06-01 08:59:14.828 7728-7728/? I/System.out: image=null
06-01 08:59:14.828 7728-7728/? I/System.out: imagepath=/data/user/0/s.e.so56392635storeimage/files/myimagestore/sample001.jpg
06-01 08:59:14.828 7728-7728/? I/System.out: }
06-01 08:59:14.828 7728-7728/? I/System.out: 1 {
06-01 08:59:14.828 7728-7728/? I/System.out: _id=2
06-01 08:59:14.828 7728-7728/? I/System.out: name=sample002.jpg
06-01 08:59:14.828 7728-7728/? I/System.out: stok=stock for sample002.jpg
06-01 08:59:14.828 7728-7728/? I/System.out: jual=jual for sample002.jpg
06-01 08:59:14.828 7728-7728/? I/System.out: image=null
06-01 08:59:14.828 7728-7728/? I/System.out: imagepath=/data/user/0/s.e.so56392635storeimage/files/myimagestore/sample002.jpg
06-01 08:59:14.828 7728-7728/? I/System.out: }
06-01 08:59:14.829 7728-7728/? I/System.out: 2 {
06-01 08:59:14.829 7728-7728/? I/System.out: _id=3
06-01 08:59:14.829 7728-7728/? I/System.out: name=sample003.jpg
06-01 08:59:14.829 7728-7728/? I/System.out: stok=stock for sample003.jpg
06-01 08:59:14.829 7728-7728/? I/System.out: jual=jual for sample003.jpg
06-01 08:59:14.829 7728-7728/? I/System.out: image=null
06-01 08:59:14.829 7728-7728/? I/System.out: imagepath=/data/user/0/s.e.so56392635storeimage/files/myimagestore/sample003.jpg
06-01 08:59:14.829 7728-7728/? I/System.out: }
06-01 08:59:14.829 7728-7728/? I/System.out: 3 {
06-01 08:59:14.829 7728-7728/? I/System.out: _id=4
06-01 08:59:14.829 7728-7728/? I/System.out: name=sample004.jpg
06-01 08:59:14.829 7728-7728/? I/System.out: stok=stock for sample004.jpg
06-01 08:59:14.829 7728-7728/? I/System.out: jual=jual for sample004.jpg
06-01 08:59:14.829 7728-7728/? I/System.out: image=<unprintable>
06-01 08:59:14.829 7728-7728/? I/System.out: imagepath=null
06-01 08:59:14.829 7728-7728/? I/System.out: }
06-01 08:59:14.829 7728-7728/? I/System.out: 4 {
06-01 08:59:14.829 7728-7728/? I/System.out: _id=5
06-01 08:59:14.829 7728-7728/? I/System.out: name=sample005.jpg
06-01 08:59:14.829 7728-7728/? I/System.out: stok=stock for sample005.jpg
06-01 08:59:14.829 7728-7728/? I/System.out: jual=jual for sample005.jpg
06-01 08:59:14.829 7728-7728/? I/System.out: image=<unprintable>
06-01 08:59:14.829 7728-7728/? I/System.out: imagepath=null
06-01 08:59:14.829 7728-7728/? I/System.out: }
06-01 08:59:14.829 7728-7728/? I/System.out: <<<<<
Это указывает на то, что sample001.jpg - sample003.jpg хранился как файлы, например sample001.jpg был сохранен (с точки зрения БД) в / data / user / 0 / seso56392635storeimage / files /myimagestore / sample001.jpg
- очевидно, что имя пакета будет соответствовать используемому пакету, иногда вы можете увидеть / data / data / the_package_name / files / myimagestore / sample001.jpg
А также для этих 3 изображений столбец image имеет значение null .
Для двух других (меньших) изображенийстолбец image имеет значение непечатаемый (т.е. BLOB), а столбец imagepath имеет значение null .
.Для проверки или проверки следующих двух снимков экрана убедитесь, что фотографии большего размера были сохранены.
Сначала в папке ресурсов отображаются размеры файлов в соответствии с папкой ресурсов: -
Второе внутреннее хранилище приложения (данные / данные /): -
sample004.jpg и sample005.jpg не отображаются, поскольку они хранятся в БД.
Наконец, в качестве доказательства того, что меньшие изображения были сохранены, простая модификация запроса, которая извлекает курсор в соответствии с: -
Cursor csr = mDBHlpr.getData("SELECT *, length(" + SQLiteHelper.RECORD_COL_IMAGE + ") FROM RECORD;");
, приводит к: -
06-01 09:16:36.282 I/System.out: _id=4
06-01 09:16:36.282 I/System.out: name=sample004.jpg
06-01 09:16:36.282 I/System.out: stok=stock for sample004.jpg
06-01 09:16:36.282 I/System.out: jual=jual for sample004.jpg
06-01 09:16:36.282 I/System.out: image=<unprintable>
06-01 09:16:36.282 I/System.out: imagepath=null
06-01 09:16:36.282 I/System.out: length(image)=9000 <<<<<<<<<<<<
06-01 09:16:36.283 I/System.out: }
06-01 09:16:36.283 I/System.out: 4 {
06-01 09:16:36.283 I/System.out: _id=5
06-01 09:16:36.283 I/System.out: name=sample005.jpg
06-01 09:16:36.283 I/System.out: stok=stock for sample005.jpg
06-01 09:16:36.283 I/System.out: jual=jual for sample005.jpg
06-01 09:16:36.283 I/System.out: image=<unprintable>
06-01 09:16:36.283 I/System.out: imagepath=null
06-01 09:16:36.283 I/System.out: length(image)=28239 <<<<<<<<<<<<
ДополнительноSQliteHelper.java
Вот полный SQLiteHelper.java: -
public class SQLiteHelper extends SQLiteOpenHelper {
public static final int MAX_IMAGESIZETOSTORE = 1024 * 256;
public static final String DBNAME = "mydb";
public static final int DBVERSION = 1;
public static final String TBLNAME_RECORD = "record";
public static final String RECORD_COl_ID = BaseColumns._ID;
public static final String RECORD_COL_NAME = "name";
public static final String RECORD_COL_STOK = "stok";
public static final String RECORD_COL_JUAL = "jual";
public static final String RECORD_COL_IMAGE = "image";
public static final String RECORD_COL_IMAGEPATH = "imagepath";
Context mContext;
//constructor <<<<<<<<<< MODIFIED so just requires Context
//!!!!!!!!!!NOTE!!!!!!!!!! uses database/tables as defined in this class
public SQLiteHelper(Context context){
super(context,DBNAME, null, DBVERSION);
mContext = context;
}
public void queryData(String sql){
SQLiteDatabase database = getWritableDatabase();
database.execSQL(sql);
}
public long insertData(String name, String stok, String jual, byte[] image) {
SQLiteDatabase db = this.getWritableDatabase();
ContentValues cv = new ContentValues();
cv.put(RECORD_COL_NAME,name);
cv.put(RECORD_COL_STOK,stok);
cv.put(RECORD_COL_JUAL,jual);
if (image.length > 0 && image.length < MAX_IMAGESIZETOSTORE) {
cv.put(RECORD_COL_IMAGE,image);
} else {
cv.put(RECORD_COL_IMAGEPATH,StoreImage.storeImage(mContext,image,name));
}
return db.insert(TBLNAME_RECORD,null,cv);
}
//insertData
/**
public void insertData(String name, String stok, String jual, byte[] image){
SQLiteDatabase database = getWritableDatabase();
//query to insert record in database table
String sql = "INSERT INTO RECORD VALUES(NULL, ?, ?, ?, ?)"; //where "RECORD" is table name in database we will create in mainActivity
SQLiteStatement statement = database.compileStatement(sql);
statement.clearBindings();
statement.bindString(1, name);
statement.bindString(2, stok);
statement.bindString(3, jual);
statement.bindBlob(4, image);
statement.executeInsert();
}
**/
//updateData
public void updateData(String name, String stok, String jual, byte[] image, int id){
SQLiteDatabase database = getWritableDatabase();
//query to update record
String sql = "UPDATE RECORD SET name=?, stok=?, jual=?, image=? WHERE id=?";
SQLiteStatement statement = database.compileStatement(sql);
statement.bindString(1, name);
statement.bindString(2, stok);
statement.bindString(3, jual);
statement.bindBlob(4, image);
statement.bindDouble(5, (double)id);
statement.execute();
database.close();
}
//deleteData
public void deleteData(int id){
SQLiteDatabase database = getWritableDatabase();
//query to delete record using id
String sql = "DELETE FROM RECORD WHERE id=?";
SQLiteStatement statement = database.compileStatement(sql);
statement.clearBindings();
statement.bindDouble(1, (double)id);
statement.execute();
database.close();
}
public Cursor getData(String sql){
SQLiteDatabase database = getReadableDatabase();
return database.rawQuery(sql, null);
}
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL("CREATE TABLE IF NOT EXISTS " + TBLNAME_RECORD +
"(" +
RECORD_COl_ID + " INTEGER PRIMARY KEY," +
RECORD_COL_NAME + " TEXT," +
RECORD_COL_STOK + " TEXT," +
RECORD_COL_JUAL + " TEXT," +
RECORD_COL_IMAGE + " BLOB," +
RECORD_COL_IMAGEPATH + " TEXT" +
")"
);
}
@Override
public void onUpgrade(SQLiteDatabase sqLiteDatabase, int i, int i1) {
}
}
Дополнительное восстановление изображений в БД
Ограничение 256 КБ было выбрано как, возможно, разумный размер, чтобы не хранить изображения в БД.Я предполагаю, что когда вы говорите, что 2MB ограничение на загрузку , вы имеете в виду, что вы столкнулись с CursorWindow, имеющим ограничение 2MB и, следовательно, необходимость хранить пути к изображениям.
Даже 256k могут быть слишком большимитак как это может привести к 7 строкам на CursorWindow.Как таковые могут быть проблемы.Тем не менее, учитывая выводы SQlite - на 35% быстрее, чем файловая система , то при 100k вам лучше хранить изображения в базе данных. Так как такие эксперименты могут определить лучшее ограничение.