问:
I need help to store my image in internal directory and its path is insert in SQLite
I want to store large BLOBS or similar data in the SQLite database because rightnow I can't upload image with size more than 2mb

the solution for this problem's store my image in internal directory and its path is insert in SQLite DB

I've been trying to fix this past 3 days because im new in Java and i dont know how to store it

I will really appreciate if you can help me solve this

Here's my code :

CrudActivity

```<code>    EditText mEdtName, mEdtStok, mEdtJual;
    Button mBtnAdd, mBtnList;
    ImageView mImageView;

    final int REQUEST_CODE_GALLERY = 999;

    public static SQLiteHelper mSQLiteHelper;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_crud);

        mEdtName = findViewById(R.id.edtName);
        mEdtStok = findViewById(R.id.edtStok);
        mEdtJual = findViewById(R.id.edtJual);
        mBtnAdd = findViewById(R.id.btnAdd);
        mBtnList = findViewById(R.id.btnList);
        mImageView = findViewById(R.id.imageView);

        //creating database
        mSQLiteHelper = new SQLiteHelper(this, "RECORDDB.sqlite", null, 1);

        //creating table in database
        mSQLiteHelper.queryData("CREATE TABLE IF NOT EXISTS RECORD(id INTEGER PRIMARY KEY AUTOINCREMENT, name VARCHAR, stok VARCHAR, jual VARCHAR, image BLOB)");

        //select image by on imageview click
        mImageView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                //read external storage permission to select image from gallery
                //runtime permission for devices android 6.0 and above
                ActivityCompat.requestPermissions(
                        CrudActivity.this,
                        new String[]{Manifest.permission.READ_EXTERNAL_STORAGE},
                        REQUEST_CODE_GALLERY
                );
            }
        });

        //add record to sqlite
        mBtnAdd.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                try {
                    mSQLiteHelper.insertData(
                            mEdtName.getText().toString().trim(),
                            mEdtStok.getText().toString().trim(),
                            mEdtJual.getText().toString().trim(),
                            imageViewToByte(mImageView)
                    );
                    Toast.makeText(CrudActivity.this, "Added successfully", Toast.LENGTH_SHORT).show();
                    //reset views
                    mEdtName.setText("");
                    mEdtStok.setText("");
                    mEdtJual.setText("");
                    mImageView.setImageResource(R.drawable.addphoto);
                }
                catch (Exception e){
                    e.printStackTrace();
                }
            }
        });

        //show record list
        mBtnList.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                //start recordlist activity
                startActivity(new Intent(CrudActivity.this, RecordListActivity.class));
            }
        });

    }

    public static byte[] imageViewToByte(ImageView image) {
        Bitmap bitmap = ((BitmapDrawable)image.getDrawable()).getBitmap();
        ByteArrayOutputStream stream = new ByteArrayOutputStream();
        bitmap.compress(Bitmap.CompressFormat.PNG, 100, stream);
        byte[] byteArray = stream.toByteArray();
        return byteArray;
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        if (requestCode == REQUEST_CODE_GALLERY){
            if (grantResults.length>0 && grantResults[0] == PackageManager.PERMISSION_GRANTED){
                //gallery intent
                Intent galleryIntent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
                galleryIntent.setType("image/*");
                startActivityForResult(galleryIntent, REQUEST_CODE_GALLERY);
            }
            else {
                Toast.makeText(this, "Don't have permission to access file location", Toast.LENGTH_SHORT).show();
            }
            return;
        }
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        Intent intent;
        intent = new Intent(Intent.ACTION_GET_CONTENT);

        if (requestCode == REQUEST_CODE_GALLERY && resultCode == RESULT_OK){
            Uri imageUri = data.getData();
            final int takeFlags = intent.getFlags()
                    & (Intent.FLAG_GRANT_READ_URI_PERMISSION
                    | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
// Check for the freshest data.
            getContentResolver().takePersistableUriPermission(imageUri, takeFlags);
            CropImage.activity(imageUri)
                    .setGuidelines(CropImageView.Guidelines.ON) //enable image guidlines
                    .setAspectRatio(1,1)// image will be square
                    .start(this);

        }
        if (requestCode == CropImage.CROP_IMAGE_ACTIVITY_REQUEST_CODE){
            CropImage.ActivityResult result =CropImage.getActivityResult(data);
            if (resultCode == RESULT_OK){
                Uri resultUri = result.getUri();
                //set image choosed from gallery to image view
                mImageView.setImageURI(resultUri);
            }
            else if (resultCode == CropImage.CROP_IMAGE_ACTIVITY_RESULT_ERROR_CODE){
                Exception error = result.getError();
            }

        }

        super.onActivityResult(requestCode, resultCode, data);
    }
}
</code>```

SQLiteHelper

```<code>  public class SQLiteHelper extends SQLiteOpenHelper{

    //constructor
    SQLiteHelper(Context context,
                 String name,
                 SQLiteDatabase.CursorFactory factory,
                 int version){
        super(context, name, factory, version);
    }

    public void queryData(String sql){
        SQLiteDatabase database = getWritableDatabase();
        database.execSQL(sql);
    }

    //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 sqLiteDatabase) {

    }

    @Override
    public void onUpgrade(SQLiteDatabase sqLiteDatabase, int i, int i1) {

    }
}
</code>```

RecordListActivity

```<code>public class RecordListActivity extends AppCompatActivity {

    ListView mListView;
    ArrayList<Model> mList;
    RecordListAdapter mAdapter = null;

    ImageView imageViewIcon;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_record_list);

        mListView = findViewById(R.id.listView);
        mList = new ArrayList<>();
        mAdapter = new RecordListAdapter(this, R.layout.row, mList);
        mListView.setAdapter(mAdapter);

        //get all data from sqlite
        SQLiteHelper mSQLiteHelper = new SQLiteHelper(this, "RECORDDB.sqlite", null, 1);
        Cursor cursor = mSQLiteHelper.getData("SELECT * FROM RECORD");
        mList.clear();
        while (cursor.moveToNext()){
            int id = cursor.getInt(0);
            String name = cursor.getString(1);
            String stok = cursor.getString(2);
            String jual = cursor.getString(3);
            byte[] image  = cursor.getBlob(4);
            //add to list
            mList.add(new Model(id, name, stok, jual, image));
        }
        mAdapter.notifyDataSetChanged();
        if (mList.size()==0){
            //if there is no record in table of database which means listview is empty
            Toast.makeText(this, "No record found...", Toast.LENGTH_SHORT).show();
        }

        mListView.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
            @Override
            public boolean onItemLongClick(AdapterView<?> adapterView, View view, final int position, long l) {
                //alert dialog to display options of update and delete
                final CharSequence[] items = {"Update", "Delete"};

                AlertDialog.Builder dialog = new AlertDialog.Builder(RecordListActivity.this);

                dialog.setTitle("Choose an action");
                dialog.setItems(items, new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialogInterface, int i) {
                        if (i == 0){
                            //update
                            Cursor c = CrudActivity.mSQLiteHelper.getData("SELECT id FROM RECORD");
                            ArrayList<Integer> arrID = new ArrayList<Integer>();
                            while (c.moveToNext()){
                                arrID.add(c.getInt(0));
                            }
                            //show update dialog
                            showDialogUpdate(RecordListActivity.this, arrID.get(position));
                        }
                        if (i==1){
                            //delete
                            Cursor c = CrudActivity.mSQLiteHelper.getData("SELECT id FROM RECORD");
                            ArrayList<Integer> arrID = new ArrayList<Integer>();
                            while (c.moveToNext()){
                                arrID.add(c.getInt(0));
                            }
                            showDialogDelete(arrID.get(position));
                        }
                    }
                });
                dialog.show();
                return true;
            }
        });

    }

    private void showDialogDelete(final int idRecord) {
        AlertDialog.Builder dialogDelete = new AlertDialog.Builder(RecordListActivity.this);
        dialogDelete.setTitle("Warning!!");
        dialogDelete.setMessage("Are you sure to delete?");
        dialogDelete.setPositiveButton("OK", new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialogInterface, int i) {
                try {
                    CrudActivity.mSQLiteHelper.deleteData(idRecord);
                    Toast.makeText(RecordListActivity.this, "Delete successfully", Toast.LENGTH_SHORT).show();
                }
                catch (Exception e){
                    Log.e("error", e.getMessage());
                }
                updateRecordList();
            }
        });
        dialogDelete.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialogInterface, int i) {
                dialogInterface.dismiss();
            }
        });
        dialogDelete.show();
    }

    private void showDialogUpdate(Activity activity, final int position){
        final Dialog dialog = new Dialog(activity);
        dialog.setContentView(R.layout.update_dialog);
        dialog.setTitle("Update");

        imageViewIcon = dialog.findViewById(R.id.imageViewRecord);
        final EditText edtName = dialog.findViewById(R.id.edtName);
        final EditText edtStok = dialog.findViewById(R.id.edtStok);
        final EditText edtJual = dialog.findViewById(R.id.edtJual);
        Button btnUpdate = dialog.findViewById(R.id.btnUpdate);

        //set width of dialog
        int width = (int)(activity.getResources().getDisplayMetrics().widthPixels*0.95);
        //set hieght of dialog
        int height = (int)(activity.getResources().getDisplayMetrics().heightPixels*0.7);
        dialog.getWindow().setLayout(width,height);
        dialog.show();

        //in update dialog click image view to update image
        imageViewIcon.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                //check external storage permission
                ActivityCompat.requestPermissions(
                        RecordListActivity.this,
                        new String[]{Manifest.permission.READ_EXTERNAL_STORAGE},
                        888
                );
            }
        });
        btnUpdate.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                try {
                    CrudActivity.mSQLiteHelper.updateData(
                            edtName.getText().toString().trim(),
                            edtStok.getText().toString().trim(),
                            edtJual.getText().toString().trim(),
                            CrudActivity.imageViewToByte(imageViewIcon),
                            position
                    );
                    dialog.dismiss();
                    Toast.makeText(getApplicationContext(), "Update Successfull", Toast.LENGTH_SHORT).show();
                }
                catch (Exception error){
                    Log.e("Update error", error.getMessage());
                }
                updateRecordList();
            }
        });

    }

    private void updateRecordList() {
        //get all data from sqlite
        Cursor cursor = CrudActivity.mSQLiteHelper.getData("SELECT * FROM RECORD");
        mList.clear();
        while (cursor.moveToNext()){
            int id = cursor.getInt(0);
            String name = cursor.getString(1);
            String stok = cursor.getString(2);
            String jual = cursor.getString(3);
            byte[] image = cursor.getBlob(4);

            mList.add(new Model(id,name,stok,jual,image));
        }
        mAdapter.notifyDataSetChanged();
    }

    public static byte[] imageViewToByte(ImageView image) {
        Bitmap bitmap = ((BitmapDrawable)image.getDrawable()).getBitmap();
        ByteArrayOutputStream stream = new ByteArrayOutputStream();
        bitmap.compress(Bitmap.CompressFormat.JPEG, 100, stream);
        byte[] byteArray = stream.toByteArray();
        return byteArray;
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        if (requestCode == 888){
            if (grantResults.length>0 && grantResults[0] == PackageManager.PERMISSION_GRANTED){
                //gallery intent
                Intent galleryIntent = new Intent(Intent.ACTION_GET_CONTENT);
                galleryIntent.setType("image/*");
                startActivityForResult(galleryIntent, 888);
            }
            else {
                Toast.makeText(this, "Don't have permission to access file location", Toast.LENGTH_SHORT).show();
            }
            return;
        }
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        Intent intent;
        intent = new Intent(Intent.ACTION_GET_CONTENT);

        if (requestCode == 888 && resultCode == RESULT_OK){
            Uri imageUri = data.getData();
            final int takeFlags = intent.getFlags()
                    & (Intent.FLAG_GRANT_READ_URI_PERMISSION
                    | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
// Check for the freshest data.
            getContentResolver().takePersistableUriPermission(imageUri, takeFlags);
            CropImage.activity(imageUri)
                    .setGuidelines(CropImageView.Guidelines.ON) //enable image guidlines
                    .setAspectRatio(1,1)// image will be square
                    .start(this);
        }
        if (requestCode == CropImage.CROP_IMAGE_ACTIVITY_REQUEST_CODE){
            CropImage.ActivityResult result =CropImage.getActivityResult(data);
            if (resultCode == RESULT_OK){
                Uri resultUri = result.getUri();
                //set image choosed from gallery to image view
                imageViewIcon.setImageURI(resultUri);
            }
            else if (resultCode == CropImage.CROP_IMAGE_ACTIVITY_RESULT_ERROR_CODE){
                Exception error = result.getError();
            }
        }

        super.onActivityResult(requestCode, resultCode, data);
    }
}
</code>```

答:
The following demonstration will store an image either in the database or to internal storage within the app.

If the image size is < 256k (as per public static final int MAX_IMAGESIZETOSTORE = 1024 * 256;) then it will be stored in the db and be retrievable from the database.

If the image is 256k or more (with a limit of 16MB imposed for the demo as per public static final int MAXIMAGEBUFFER = 1024 * 1024 * 16;) then it will be stored in the App's Files/myimagestores directory (myimagestores directory being created by the demo) and the path to the image is stored in the database.

The demo rather than getting images from a camera, gets the images from the assets folder (5 were used for the demo).

The code will not work properly if the images are not in the assets folder and if they are not defined with matching names as per :-

```<code>String[] imagesToGet = new String[]{"sample001.jpg","sample002.jpg","sample003.jpg","sample004.jpg","sample005.jpg"};
</code>```

The code

SQLiteHelper.java

this is basically your helper with a modified insertData method that being

:-

```<code>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);
}
</code>```

The following constants are declared at the class level :-

```<code>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";
</code>```

as can be seen an additional column, imagepath has been added to store the path to image (null if the image is store in the db and vice-versa that is if the image is not stored in the db but as a file then the image column will be null).

StoreImage.java is

:-

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

As can be seen from the above the storeImage method of the StoreImage class stores the image, (the byte[] passed to the insertData method of the SQliteHelper class.

As can also be seen the above will create the myimagestore directory if need be.

MainActivity.java is

:-

```<code>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;
    }
}
</code>```

The getImage method, the bulk of the activity, retrieves an image from the assets folder (the demo images).

The 5 demo images are processed in a loop and added to the database via the insertData method.

After the inserts the all data is extracted into a Cursor and the Cursor is dumped (written to the log).

Example Run :-

With the images copied into the assets folder as per :-

And the App run then the log contains :-

```<code>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: <<<<<
</code>```

This indicates that sample001.jpg -  sample003.jpg were stored as files e.g. sample001.jpg was stored (s far as the db is concerned) at /data/user/0/s.e.so56392635storeimage/files/myimagestore/sample001.jpg

obviously the package name will be as per the package used, sometimes you may see /data/data/the_package_name/files/myimagestore/sample001.jpg

And also for those 3 images the image column is null.

For the other two (smaller) images, the image column is unprintable (i.e. a BLOB) and the imagepath column is null.

In addition to the above test/check the following two screen shots, verify that the larger photos have been stored.

First the assets folder showing file sizes as per the assets folder :-

Second the App's internal storage (data/data/) :-

sample004.jpg and sample005.jpg don't appear as they have been stored in the DB.

Finally as proof that smaller images have been stored then a simple modification to the query that extracts the cursor as per :-

```<code>Cursor csr = mDBHlpr.getData("SELECT *, length(" + SQLiteHelper.RECORD_COL_IMAGE + ") FROM RECORD;");
</code>```

results in :-

```<code>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 <<<<<<<<<<<<
</code>```

Additional SQliteHelper.java

Here's complete SQLiteHelper.java :-

```<code>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) {

    }
}
</code>```

Additional re storing images in DB

The 256k limitation has been chosen as being perhaps a reasonable size to not store images in the DB. I guess when you say the 2MB download limit, you mean that you've encountered a CursorWindow having a 2MB limit and hence the need to store image paths.

Even 256k might be too large as that could result in a 7 rows per CursorWindow. As such there could be issues. However, considering the findings of SQlite - 35% Faster Than The Filesystem then at 100k you are potentially better off storing the images in the database. As such experimentation may determine a better limitation.

Body:
I want to store large BLOBS or similar data in the SQLite database because rightnow I can't upload image with size more than 2mb

the solution for this problem's store my image in internal directory and its path is insert in SQLite DB

I've been trying to fix this past 3 days because im new in Java and i dont know how to store it

I will really appreciate if you can help me solve this

Here's my code :

CrudActivity

    EditText mEdtName, mEdtStok, mEdtJual;
    Button mBtnAdd, mBtnList;
    ImageView mImageView;

    final int REQUEST_CODE_GALLERY = 999;

    public static SQLiteHelper mSQLiteHelper;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_crud);

        mEdtName = findViewById(R.id.edtName);
        mEdtStok = findViewById(R.id.edtStok);
        mEdtJual = findViewById(R.id.edtJual);
        mBtnAdd = findViewById(R.id.btnAdd);
        mBtnList = findViewById(R.id.btnList);
        mImageView = findViewById(R.id.imageView);

        //creating database
        mSQLiteHelper = new SQLiteHelper(this, "RECORDDB.sqlite", null, 1);

        //creating table in database
        mSQLiteHelper.queryData("CREATE TABLE IF NOT EXISTS RECORD(id INTEGER PRIMARY KEY AUTOINCREMENT, name VARCHAR, stok VARCHAR, jual VARCHAR, image BLOB)");

        //select image by on imageview click
        mImageView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                //read external storage permission to select image from gallery
                //runtime permission for devices android 6.0 and above
                ActivityCompat.requestPermissions(
                        CrudActivity.this,
                        new String[]{Manifest.permission.READ_EXTERNAL_STORAGE},
                        REQUEST_CODE_GALLERY
                );
            }
        });

        //add record to sqlite
        mBtnAdd.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                try {
                    mSQLiteHelper.insertData(
                            mEdtName.getText().toString().trim(),
                            mEdtStok.getText().toString().trim(),
                            mEdtJual.getText().toString().trim(),
                            imageViewToByte(mImageView)
                    );
                    Toast.makeText(CrudActivity.this, "Added successfully", Toast.LENGTH_SHORT).show();
                    //reset views
                    mEdtName.setText("");
                    mEdtStok.setText("");
                    mEdtJual.setText("");
                    mImageView.setImageResource(R.drawable.addphoto);
                }
                catch (Exception e){
                    e.printStackTrace();
                }
            }
        });

        //show record list
        mBtnList.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                //start recordlist activity
                startActivity(new Intent(CrudActivity.this, RecordListActivity.class));
            }
        });

    }

    public static byte[] imageViewToByte(ImageView image) {
        Bitmap bitmap = ((BitmapDrawable)image.getDrawable()).getBitmap();
        ByteArrayOutputStream stream = new ByteArrayOutputStream();
        bitmap.compress(Bitmap.CompressFormat.PNG, 100, stream);
        byte[] byteArray = stream.toByteArray();
        return byteArray;
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        if (requestCode == REQUEST_CODE_GALLERY){
            if (grantResults.length>0 && grantResults[0] == PackageManager.PERMISSION_GRANTED){
                //gallery intent
                Intent galleryIntent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
                galleryIntent.setType("image/*");
                startActivityForResult(galleryIntent, REQUEST_CODE_GALLERY);
            }
            else {
                Toast.makeText(this, "Don't have permission to access file location", Toast.LENGTH_SHORT).show();
            }
            return;
        }
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        Intent intent;
        intent = new Intent(Intent.ACTION_GET_CONTENT);

        if (requestCode == REQUEST_CODE_GALLERY && resultCode == RESULT_OK){
            Uri imageUri = data.getData();
            final int takeFlags = intent.getFlags()
                    & (Intent.FLAG_GRANT_READ_URI_PERMISSION
                    | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
// Check for the freshest data.
            getContentResolver().takePersistableUriPermission(imageUri, takeFlags);
            CropImage.activity(imageUri)
                    .setGuidelines(CropImageView.Guidelines.ON) //enable image guidlines
                    .setAspectRatio(1,1)// image will be square
                    .start(this);

        }
        if (requestCode == CropImage.CROP_IMAGE_ACTIVITY_REQUEST_CODE){
            CropImage.ActivityResult result =CropImage.getActivityResult(data);
            if (resultCode == RESULT_OK){
                Uri resultUri = result.getUri();
                //set image choosed from gallery to image view
                mImageView.setImageURI(resultUri);
            }
            else if (resultCode == CropImage.CROP_IMAGE_ACTIVITY_RESULT_ERROR_CODE){
                Exception error = result.getError();
            }

        }

        super.onActivityResult(requestCode, resultCode, data);
    }
}

SQLiteHelper

  public class SQLiteHelper extends SQLiteOpenHelper{

    //constructor
    SQLiteHelper(Context context,
                 String name,
                 SQLiteDatabase.CursorFactory factory,
                 int version){
        super(context, name, factory, version);
    }

    public void queryData(String sql){
        SQLiteDatabase database = getWritableDatabase();
        database.execSQL(sql);
    }

    //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 sqLiteDatabase) {

    }

    @Override
    public void onUpgrade(SQLiteDatabase sqLiteDatabase, int i, int i1) {

    }
}

RecordListActivity

public class RecordListActivity extends AppCompatActivity {

    ListView mListView;
    ArrayList<Model> mList;
    RecordListAdapter mAdapter = null;

    ImageView imageViewIcon;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_record_list);

        mListView = findViewById(R.id.listView);
        mList = new ArrayList<>();
        mAdapter = new RecordListAdapter(this, R.layout.row, mList);
        mListView.setAdapter(mAdapter);

        //get all data from sqlite
        SQLiteHelper mSQLiteHelper = new SQLiteHelper(this, "RECORDDB.sqlite", null, 1);
        Cursor cursor = mSQLiteHelper.getData("SELECT * FROM RECORD");
        mList.clear();
        while (cursor.moveToNext()){
            int id = cursor.getInt(0);
            String name = cursor.getString(1);
            String stok = cursor.getString(2);
            String jual = cursor.getString(3);
            byte[] image  = cursor.getBlob(4);
            //add to list
            mList.add(new Model(id, name, stok, jual, image));
        }
        mAdapter.notifyDataSetChanged();
        if (mList.size()==0){
            //if there is no record in table of database which means listview is empty
            Toast.makeText(this, "No record found...", Toast.LENGTH_SHORT).show();
        }

        mListView.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
            @Override
            public boolean onItemLongClick(AdapterView<?> adapterView, View view, final int position, long l) {
                //alert dialog to display options of update and delete
                final CharSequence[] items = {"Update", "Delete"};

                AlertDialog.Builder dialog = new AlertDialog.Builder(RecordListActivity.this);

                dialog.setTitle("Choose an action");
                dialog.setItems(items, new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialogInterface, int i) {
                        if (i == 0){
                            //update
                            Cursor c = CrudActivity.mSQLiteHelper.getData("SELECT id FROM RECORD");
                            ArrayList<Integer> arrID = new ArrayList<Integer>();
                            while (c.moveToNext()){
                                arrID.add(c.getInt(0));
                            }
                            //show update dialog
                            showDialogUpdate(RecordListActivity.this, arrID.get(position));
                        }
                        if (i==1){
                            //delete
                            Cursor c = CrudActivity.mSQLiteHelper.getData("SELECT id FROM RECORD");
                            ArrayList<Integer> arrID = new ArrayList<Integer>();
                            while (c.moveToNext()){
                                arrID.add(c.getInt(0));
                            }
                            showDialogDelete(arrID.get(position));
                        }
                    }
                });
                dialog.show();
                return true;
            }
        });

    }

    private void showDialogDelete(final int idRecord) {
        AlertDialog.Builder dialogDelete = new AlertDialog.Builder(RecordListActivity.this);
        dialogDelete.setTitle("Warning!!");
        dialogDelete.setMessage("Are you sure to delete?");
        dialogDelete.setPositiveButton("OK", new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialogInterface, int i) {
                try {
                    CrudActivity.mSQLiteHelper.deleteData(idRecord);
                    Toast.makeText(RecordListActivity.this, "Delete successfully", Toast.LENGTH_SHORT).show();
                }
                catch (Exception e){
                    Log.e("error", e.getMessage());
                }
                updateRecordList();
            }
        });
        dialogDelete.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialogInterface, int i) {
                dialogInterface.dismiss();
            }
        });
        dialogDelete.show();
    }

    private void showDialogUpdate(Activity activity, final int position){
        final Dialog dialog = new Dialog(activity);
        dialog.setContentView(R.layout.update_dialog);
        dialog.setTitle("Update");

        imageViewIcon = dialog.findViewById(R.id.imageViewRecord);
        final EditText edtName = dialog.findViewById(R.id.edtName);
        final EditText edtStok = dialog.findViewById(R.id.edtStok);
        final EditText edtJual = dialog.findViewById(R.id.edtJual);
        Button btnUpdate = dialog.findViewById(R.id.btnUpdate);

        //set width of dialog
        int width = (int)(activity.getResources().getDisplayMetrics().widthPixels*0.95);
        //set hieght of dialog
        int height = (int)(activity.getResources().getDisplayMetrics().heightPixels*0.7);
        dialog.getWindow().setLayout(width,height);
        dialog.show();

        //in update dialog click image view to update image
        imageViewIcon.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                //check external storage permission
                ActivityCompat.requestPermissions(
                        RecordListActivity.this,
                        new String[]{Manifest.permission.READ_EXTERNAL_STORAGE},
                        888
                );
            }
        });
        btnUpdate.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                try {
                    CrudActivity.mSQLiteHelper.updateData(
                            edtName.getText().toString().trim(),
                            edtStok.getText().toString().trim(),
                            edtJual.getText().toString().trim(),
                            CrudActivity.imageViewToByte(imageViewIcon),
                            position
                    );
                    dialog.dismiss();
                    Toast.makeText(getApplicationContext(), "Update Successfull", Toast.LENGTH_SHORT).show();
                }
                catch (Exception error){
                    Log.e("Update error", error.getMessage());
                }
                updateRecordList();
            }
        });

    }

    private void updateRecordList() {
        //get all data from sqlite
        Cursor cursor = CrudActivity.mSQLiteHelper.getData("SELECT * FROM RECORD");
        mList.clear();
        while (cursor.moveToNext()){
            int id = cursor.getInt(0);
            String name = cursor.getString(1);
            String stok = cursor.getString(2);
            String jual = cursor.getString(3);
            byte[] image = cursor.getBlob(4);

            mList.add(new Model(id,name,stok,jual,image));
        }
        mAdapter.notifyDataSetChanged();
    }

    public static byte[] imageViewToByte(ImageView image) {
        Bitmap bitmap = ((BitmapDrawable)image.getDrawable()).getBitmap();
        ByteArrayOutputStream stream = new ByteArrayOutputStream();
        bitmap.compress(Bitmap.CompressFormat.JPEG, 100, stream);
        byte[] byteArray = stream.toByteArray();
        return byteArray;
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        if (requestCode == 888){
            if (grantResults.length>0 && grantResults[0] == PackageManager.PERMISSION_GRANTED){
                //gallery intent
                Intent galleryIntent = new Intent(Intent.ACTION_GET_CONTENT);
                galleryIntent.setType("image/*");
                startActivityForResult(galleryIntent, 888);
            }
            else {
                Toast.makeText(this, "Don't have permission to access file location", Toast.LENGTH_SHORT).show();
            }
            return;
        }
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        Intent intent;
        intent = new Intent(Intent.ACTION_GET_CONTENT);

        if (requestCode == 888 && resultCode == RESULT_OK){
            Uri imageUri = data.getData();
            final int takeFlags = intent.getFlags()
                    & (Intent.FLAG_GRANT_READ_URI_PERMISSION
                    | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
// Check for the freshest data.
            getContentResolver().takePersistableUriPermission(imageUri, takeFlags);
            CropImage.activity(imageUri)
                    .setGuidelines(CropImageView.Guidelines.ON) //enable image guidlines
                    .setAspectRatio(1,1)// image will be square
                    .start(this);
        }
        if (requestCode == CropImage.CROP_IMAGE_ACTIVITY_REQUEST_CODE){
            CropImage.ActivityResult result =CropImage.getActivityResult(data);
            if (resultCode == RESULT_OK){
                Uri resultUri = result.getUri();
                //set image choosed from gallery to image view
                imageViewIcon.setImageURI(resultUri);
            }
            else if (resultCode == CropImage.CROP_IMAGE_ACTIVITY_RESULT_ERROR_CODE){
                Exception error = result.getError();
            }
        }

        super.onActivityResult(requestCode, resultCode, data);
    }
}

Body:
The following demonstration will store an image either in the database or to internal storage within the app.

If the image size is < 256k (as per public static final int MAX_IMAGESIZETOSTORE = 1024 * 256;) then it will be stored in the db and be retrievable from the database.

If the image is 256k or more (with a limit of 16MB imposed for the demo as per public static final int MAXIMAGEBUFFER = 1024 * 1024 * 16;) then it will be stored in the App's Files/myimagestores directory (myimagestores directory being created by the demo) and the path to the image is stored in the database.

The demo rather than getting images from a camera, gets the images from the assets folder (5 were used for the demo).

The code will not work properly if the images are not in the assets folder and if they are not defined with matching names as per :-

String[] imagesToGet = new String[]{"sample001.jpg","sample002.jpg","sample003.jpg","sample004.jpg","sample005.jpg"};

The code

SQLiteHelper.java

this is basically your helper with a modified insertData method that being

:-

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

The following constants are declared at the class level :-

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";

as can be seen an additional column, imagepath has been added to store the path to image (null if the image is store in the db and vice-versa that is if the image is not stored in the db but as a file then the image column will be 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();
    }
}

As can be seen from the above the storeImage method of the StoreImage class stores the image, (the byte[] passed to the insertData method of the SQliteHelper class.

As can also be seen the above will create the myimagestore directory if need be.

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

The getImage method, the bulk of the activity, retrieves an image from the assets folder (the demo images).

The 5 demo images are processed in a loop and added to the database via the insertData method.

After the inserts the all data is extracted into a Cursor and the Cursor is dumped (written to the log).

Example Run :-

With the images copied into the assets folder as per :-

And the App run then the log contains :-

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: <<<<<

This indicates that sample001.jpg -  sample003.jpg were stored as files e.g. sample001.jpg was stored (s far as the db is concerned) at /data/user/0/s.e.so56392635storeimage/files/myimagestore/sample001.jpg

obviously the package name will be as per the package used, sometimes you may see /data/data/the_package_name/files/myimagestore/sample001.jpg

And also for those 3 images the image column is null.

For the other two (smaller) images, the image column is unprintable (i.e. a BLOB) and the imagepath column is null.

In addition to the above test/check the following two screen shots, verify that the larger photos have been stored.

First the assets folder showing file sizes as per the assets folder :-

Second the App's internal storage (data/data/) :-

sample004.jpg and sample005.jpg don't appear as they have been stored in the DB.

Finally as proof that smaller images have been stored then a simple modification to the query that extracts the cursor as per :-

Cursor csr = mDBHlpr.getData("SELECT *, length(" + SQLiteHelper.RECORD_COL_IMAGE + ") FROM RECORD;");

results in :-

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 <<<<<<<<<<<<

Additional SQliteHelper.java

Here's complete 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) {

    }
}

Additional re storing images in DB

The 256k limitation has been chosen as being perhaps a reasonable size to not store images in the DB. I guess when you say the 2MB download limit, you mean that you've encountered a CursorWindow having a 2MB limit and hence the need to store image paths.

Even 256k might be too large as that could result in a 7 rows per CursorWindow. As such there could be issues. However, considering the findings of SQlite - 35% Faster Than The Filesystem then at 100k you are potentially better off storing the images in the database. As such experimentation may determine a better limitation.


来源: stackexchange

问:
Is it possible to include a C# variable in a string variable without using a concatenator?
Does .NET 3.5 C# allow us to include a variable within a string variable without having to use the + concatenator (or string.Format(), for that matter).

For example (In the pseudo, I'm using a $ symbol to specify the variable):

```<code>DateTime d = DateTime.Now;
string s = "The date is $d";
Console.WriteLine(s);
</code>```

Output:

The date is 4/12/2011 11:56:39 AM

Edit

Due to the handful of responses that suggested string.Format(), I can only assume that my original post wasn't clear when I mentioned "...(or string.Format(), for that matter)". To be clear, I'm well aware of the string.Format() method. However, in my specific project that I'm working on, string.Format() doesn't help me (it's actually worse than the + concatenator).

Also, I'm inferring that most/all of you are wondering what the motive behind my question is (I suppose I'd feel the same way if I read my question as is).

If you are one of the curious, here's the short of it:

I'm creating a web app running on a Windows CE device. Due to how the web server works, I create the entire web page content (css, js, html, etc) within a string variable. For example, my .cs managed code might have something like this:

```<code>string GetPageData()
    {
    string title = "Hello";
    DateTime date = DateTime.Now;

    string html = @"
    <!DOCTYPE html PUBLIC ...>
    <html>
    <head>
        <title>$title</title>
    </head>
    <body>
    <div>Hello StackO</div>
    <div>The date is $date</div>
    </body>
    </html>
    ";

}
</code>```

As you can see, having the ability to specify a variable without the need to concatenate, makes things a bit easier - especially when the content increases in size.

答:
Or combined:

```<code>Console.WriteLine("The date is {0}", DateTime.Now);
</code>```

Extra info (in response to BrandonZeider):

Yep, it is kind-a important for people to realize that string conversion is automatically done. Manually adding ToString is broken, e.g.:

```<code>string value = null;
Console.WriteLine("The value is '{0}'", value); // OK
Console.WriteLine("The value is '{0}'", value.ToString()); // FAILURE
</code>```

Also, this becomes a lot less trivial once you realize that the stringification is not equivalent to using .ToString(). You can have format specifiers, and even custom format format providers... It is interesting enough to teach people to leverage String.Format instead of doing it manually.

ContentLicense: CC BY-SA 3.0

Body:
Does .NET 3.5 C# allow us to include a variable within a string variable without having to use the + concatenator (or string.Format(), for that matter).

For example (In the pseudo, I'm using a $ symbol to specify the variable):

DateTime d = DateTime.Now;
string s = "The date is $d";
Console.WriteLine(s);

Output:

The date is 4/12/2011 11:56:39 AM

Edit

Due to the handful of responses that suggested string.Format(), I can only assume that my original post wasn't clear when I mentioned "...(or string.Format(), for that matter)". To be clear, I'm well aware of the string.Format() method. However, in my specific project that I'm working on, string.Format() doesn't help me (it's actually worse than the + concatenator).

Also, I'm inferring that most/all of you are wondering what the motive behind my question is (I suppose I'd feel the same way if I read my question as is).

If you are one of the curious, here's the short of it:

I'm creating a web app running on a Windows CE device. Due to how the web server works, I create the entire web page content (css, js, html, etc) within a string variable. For example, my .cs managed code might have something like this:

string GetPageData()
    {
    string title = "Hello";
    DateTime date = DateTime.Now;

    string html = @"
    <!DOCTYPE html PUBLIC ...>

        <title>$title</title>

Hello StackO

The date is $date

    ";

}

As you can see, having the ability to specify a variable without the need to concatenate, makes things a bit easier - especially when the content increases in size.

Body:
Or combined:

Console.WriteLine("The date is {0}", DateTime.Now);

Extra info (in response to BrandonZeider):

Yep, it is kind-a important for people to realize that string conversion is automatically done. Manually adding ToString is broken, e.g.:

string value = null;
Console.WriteLine("The value is '{0}'", value); // OK
Console.WriteLine("The value is '{0}'", value.ToString()); // FAILURE

Also, this becomes a lot less trivial once you realize that the stringification is not equivalent to using .ToString(). You can have format specifiers, and even custom format format providers... It is interesting enough to teach people to leverage String.Format instead of doing it manually.


问:
gcloud ML engine - Keras not running on GPU
I'm new with Google Cloud Machine Learning Engine,
I'm trying to train a DL algorithm for image classification based on Keras in gcloud.
In order to configure the GPU on gcloud I have included 'tensorflow-gpu' in the setup.py install_requires.
My cloud-gpu.yaml is the following

```<code>trainingInput:
  scaleTier: BASIC_GPU
  runtimeVersion: "1.0"
</code>```

In the code I've added:

```<code>sess = tf.Session(config=tf.ConfigProto(log_device_placement=True))
</code>```

at the beginning and

```<code>with tf.device('/gpu:0'):
</code>```

before any Keras code.

The result is that gcloud is recognising the gpu but not using it, as you can see from

Screenshot of actual cloud training:

```<code>INFO    2018-11-18 12:19:59 -0600   master-replica-0        Epoch 1/20
INFO    2018-11-18 12:20:56 -0600   master-replica-0          1/219 [..............................] - ETA: 4:17:12 - loss: 0.8846 - acc: 0.5053 - f1_measure: 0.1043
INFO    2018-11-18 12:21:57 -0600   master-replica-0          2/219 [..............................] - ETA: 3:51:32 - loss: 0.8767 - acc: 0.5018 - f1_measure: 0.1013
INFO    2018-11-18 12:22:59 -0600   master-replica-0          3/219 [..............................] - ETA: 3:46:49 - loss: 0.8634 - acc: 0.5039 - f1_measure: 0.1010
INFO    2018-11-18 12:23:58 -0600   master-replica-0          4/219 [..............................] - ETA: 3:44:59 - loss: 0.8525 - acc: 0.5045 - f1_measure: 0.0991
INFO    2018-11-18 12:24:48 -0600   master-replica-0          5/219 [..............................] - ETA: 3:41:17 - loss: 0.8434 - acc: 0.5031 - f1_measure: 0.0992Sun Nov 18 18:24:48 2018
INFO    2018-11-18 12:24:48 -0600   master-replica-0        +-----------------------------------------------------------------------------+
INFO    2018-11-18 12:24:48 -0600   master-replica-0        | NVIDIA-SMI 396.26                 Driver Version: 396.26                    |
INFO    2018-11-18 12:24:48 -0600   master-replica-0        |-------------------------------+----------------------+----------------------+
INFO    2018-11-18 12:24:48 -0600   master-replica-0        | GPU  Name        Persistence-M| Bus-Id        Disp.A | Volatile Uncorr. ECC |
INFO    2018-11-18 12:24:48 -0600   master-replica-0        | Fan  Temp  Perf  Pwr:Usage/Cap|         Memory-Usage | GPU-Util  Compute M. |
INFO    2018-11-18 12:24:48 -0600   master-replica-0        |===============================+======================+======================|
INFO    2018-11-18 12:24:48 -0600   master-replica-0        |   0  Tesla K80           Off  | 00000000:00:04.0 Off |                    0 |
INFO    2018-11-18 12:24:48 -0600   master-replica-0        | N/A   32C    P0    56W / 149W |  10955MiB / 11441MiB |      0%      Default |
INFO    2018-11-18 12:24:48 -0600   master-replica-0        +-------------------------------+----------------------+----------------------+
INFO    2018-11-18 12:24:48 -0600   master-replica-0
INFO    2018-11-18 12:24:48 -0600   master-replica-0        +-----------------------------------------------------------------------------+
INFO    2018-11-18 12:24:48 -0600   master-replica-0        | Processes:                                                       GPU Memory |
INFO    2018-11-18 12:24:48 -0600   master-replica-0        |  GPU       PID   Type   Process name                             Usage      |
INFO    2018-11-18 12:24:48 -0600   master-replica-0        |=============================================================================|
INFO    2018-11-18 12:24:48 -0600   master-replica-0        +-----------------------------------------------------------------------------+
</code>```

Basically the GPU usage stays at 0% during the training, how can this be possible?

答:
I recommend to use the standard_gpu which has the same n1-standard-8 with one k80 GPU in the cloud-gpu.yaml:

```<code>trainingInput:
  scaleTier: CUSTOM
  # standard_gpu provides 1 GPU. Change to complex_model_m_gpu for 4 GPUs
  masterType: standard_gpu
  runtimeVersion: "1.5"
</code>```

this:

```<code>with tf.device('/gpu:0'):
</code>```

should be:

```<code>with tf.device('/device:GPU:0'):
</code>```

I recommend to review this cnn_with_keras.py to have a better example.

ContentLicense: CC BY-SA 4.0

Body:
I'm new with Google Cloud Machine Learning Engine,
I'm trying to train a DL algorithm for image classification based on Keras in gcloud.
In order to configure the GPU on gcloud I have included 'tensorflow-gpu' in the setup.py install_requires.
My cloud-gpu.yaml is the following

trainingInput:
  scaleTier: BASIC_GPU
  runtimeVersion: "1.0"

In the code I've added:

sess = tf.Session(config=tf.ConfigProto(log_device_placement=True))

at the beginning and

with tf.device('/gpu:0'):

before any Keras code.

The result is that gcloud is recognising the gpu but not using it, as you can see from

Screenshot of actual cloud training:

INFO    2018-11-18 12:19:59 -0600   master-replica-0        Epoch 1/20
INFO    2018-11-18 12:20:56 -0600   master-replica-0          1/219 [..............................] - ETA: 4:17:12 - loss: 0.8846 - acc: 0.5053 - f1_measure: 0.1043
INFO    2018-11-18 12:21:57 -0600   master-replica-0          2/219 [..............................] - ETA: 3:51:32 - loss: 0.8767 - acc: 0.5018 - f1_measure: 0.1013
INFO    2018-11-18 12:22:59 -0600   master-replica-0          3/219 [..............................] - ETA: 3:46:49 - loss: 0.8634 - acc: 0.5039 - f1_measure: 0.1010
INFO    2018-11-18 12:23:58 -0600   master-replica-0          4/219 [..............................] - ETA: 3:44:59 - loss: 0.8525 - acc: 0.5045 - f1_measure: 0.0991
INFO    2018-11-18 12:24:48 -0600   master-replica-0          5/219 [..............................] - ETA: 3:41:17 - loss: 0.8434 - acc: 0.5031 - f1_measure: 0.0992Sun Nov 18 18:24:48 2018
INFO    2018-11-18 12:24:48 -0600   master-replica-0        +-----------------------------------------------------------------------------+
INFO    2018-11-18 12:24:48 -0600   master-replica-0        | NVIDIA-SMI 396.26                 Driver Version: 396.26                    |
INFO    2018-11-18 12:24:48 -0600   master-replica-0        |-------------------------------+----------------------+----------------------+
INFO    2018-11-18 12:24:48 -0600   master-replica-0        | GPU  Name        Persistence-M| Bus-Id        Disp.A | Volatile Uncorr. ECC |
INFO    2018-11-18 12:24:48 -0600   master-replica-0        | Fan  Temp  Perf  Pwr:Usage/Cap|         Memory-Usage | GPU-Util  Compute M. |
INFO    2018-11-18 12:24:48 -0600   master-replica-0        |===============================+======================+======================|
INFO    2018-11-18 12:24:48 -0600   master-replica-0        |   0  Tesla K80           Off  | 00000000:00:04.0 Off |                    0 |
INFO    2018-11-18 12:24:48 -0600   master-replica-0        | N/A   32C    P0    56W / 149W |  10955MiB / 11441MiB |      0%      Default |
INFO    2018-11-18 12:24:48 -0600   master-replica-0        +-------------------------------+----------------------+----------------------+
INFO    2018-11-18 12:24:48 -0600   master-replica-0
INFO    2018-11-18 12:24:48 -0600   master-replica-0        +-----------------------------------------------------------------------------+
INFO    2018-11-18 12:24:48 -0600   master-replica-0        | Processes:                                                       GPU Memory |
INFO    2018-11-18 12:24:48 -0600   master-replica-0        |  GPU       PID   Type   Process name                             Usage      |
INFO    2018-11-18 12:24:48 -0600   master-replica-0        |=============================================================================|
INFO    2018-11-18 12:24:48 -0600   master-replica-0        +-----------------------------------------------------------------------------+

Basically the GPU usage stays at 0% during the training, how can this be possible?

Body:
I recommend to use the standard_gpu which has the same n1-standard-8 with one k80 GPU in the cloud-gpu.yaml:

trainingInput:
  scaleTier: CUSTOM
  # standard_gpu provides 1 GPU. Change to complex_model_m_gpu for 4 GPUs
  masterType: standard_gpu
  runtimeVersion: "1.5"

this:

with tf.device('/gpu:0'):

should be:

with tf.device('/device:GPU:0'):

I recommend to review this cnn_with_keras.py to have a better example.


问:
With printing Entry´s text, last character is dismissed. How to fix?
I want to print the text of an Entry each time a new character is written.
By doing this with binding  and a command to the widget the last character isn't printed.

I guess that the parameter 'textvariable' is getting updated after binding command had been executed. How to fix this?

```<code>from tkinter import *
master = Tk()
var = StringVar()

def execute_e(key):
    print(var.get())

E = Entry(master, width=30, textvariable=var)
E.pack()
E.bind('<Key>', execute_e)
</code>```

答:
I feel like this is a question of event handler. When a key is typed, your code first register a key press and execute the bound command execute_e.  Only after it has processed this and your event handler has return will it update the entry with the character and proceed to update the tkinter variable.

Your print command therefore comes in before your variable have been updated and you print the previous version of your variable.  If you try deleting a character from your entry, you'll see that you get the previous string with the character you have just erased.

The easiest way around that problem for you is probably to bind the command to the tkinter variable rather than the keybind.  Do so using trace when the variable is writen like so :

```<code>var.trace('w', execute_e)
</code>```

There are also some methods to manipulate the event handler and decide in which order to execute commands.  root.after_idle will execute a command when the code has nothing else to do (when it has computed everything else you asked it to do).  Try out this version of your code :

```<code>from tkinter import *
master = Tk()
var = StringVar()

def execute_e(*key):
    def printy():
        print(var.get())
    master.after_idle(printy)

E = Entry(master, width=30, textvariable=var)
E.pack()
E.bind('<Key>', execute_e)
master.mainloop()
</code>```

Body:
I want to print the text of an Entry each time a new character is written.
By doing this with binding  and a command to the widget the last character isn't printed.

I guess that the parameter 'textvariable' is getting updated after binding command had been executed. How to fix this?

from tkinter import *
master = Tk()
var = StringVar()

def execute_e(key):
    print(var.get())

E = Entry(master, width=30, textvariable=var)
E.pack()
E.bind('<Key>', execute_e)

Body:
I feel like this is a question of event handler. When a key is typed, your code first register a key press and execute the bound command execute_e.  Only after it has processed this and your event handler has return will it update the entry with the character and proceed to update the tkinter variable.

Your print command therefore comes in before your variable have been updated and you print the previous version of your variable.  If you try deleting a character from your entry, you'll see that you get the previous string with the character you have just erased.

The easiest way around that problem for you is probably to bind the command to the tkinter variable rather than the keybind.  Do so using trace when the variable is writen like so :

var.trace('w', execute_e)

There are also some methods to manipulate the event handler and decide in which order to execute commands.  root.after_idle will execute a command when the code has nothing else to do (when it has computed everything else you asked it to do).  Try out this version of your code :

from tkinter import *
master = Tk()
var = StringVar()

def execute_e(*key):
    def printy():
        print(var.get())
    master.after_idle(printy)

E = Entry(master, width=30, textvariable=var)
E.pack()
E.bind('<Key>', execute_e)
master.mainloop()


问:
How to prove that "Type <> Set" (i.e. Type is not equal to Set) in Coq?
Is there an equality or inequality relation between Type and Set in Coq ?

I am learning about Coq's type system and understand that the type of Set is Type@{Set+1}, and that the type of Type@{k} is Type@{k+1}. I tried to prove that Type = Set, and then tried to prove  Type <> Set, but I failed in both cases.

I started with

```<code>Lemma set_is_type :  Type = Set.
Proof.
reflexivity.
</code>```

which gives an error message saying that Unable to unify "Set" with "Type@{Top.74}".

Then I tried

```<code>Lemma set_is_not_type : Type <> Set.
Proof.
intros contra.
</code>```

At this point I do not know how to proceed. The tactic discriminate did not work, neither inversion contra.

Which one of the above two lemmas can be proved?

答:
This actually isn't an entirely trivial theorem. To show that Type = Set results in a paradox (and hence that having separate levels of Type is necessary), you'll need to use a standard result akin to Russell's paradox from set theory. Specifically, you'll need Hurken's paradox, which essentially says that smaller Types can't be on equal footing to larger Types (remember that Type is polymorphic in Coq, and in particular, Set is the lowest level (or second lowest if you include Prop)).

The particular theorem we want can be found in the standard library.

```<code>Require Logic.Hurkens.
Import Logic.Hurkens.TypeNeqSmallType.

Check paradox.
</code>```

paradox has the type signature forall A : Type, Type = A -> False. This is pretty much what we want to prove, since Set: Type (at least if Type is large enough).

```<code>Lemma set_is_not_type: Type <> Set.
Proof.
  intro F.
  exact (paradox _ F).
Defined.
</code>```

Coq automatically sets restrictions on the Type in this lemma to ensure that Set: Type.

On the other hand, Set is equal to some level of Type, so we should be able to prove that Type = Set with some different constraints on this Type. The easiest way I found to do this was to prove that Type = Type, but then instantiate this theorem with Set. For whatever reason, as you found, reflexivity can't enforce universe constraints by itself. To do this, we need to make both the lemmas universe polymorphic so that they can be instantiated with a particular universe level.

```<code>Polymorphic Lemma type_is_type: Type = Type.
Proof.
  reflexivity.
Defined.

Polymorphic Lemma type_is_set: Type = Set.
Proof.
  apply type_is_type.
Defined.
</code>```

The easier way to make everything universe polymorphic is to put Set Universe Polymorphism. before everything.

Body:
Is there an equality or inequality relation between Type and Set in Coq ?

I am learning about Coq's type system and understand that the type of Set is Type@{Set+1}, and that the type of Type@{k} is Type@{k+1}. I tried to prove that Type = Set, and then tried to prove  Type <> Set, but I failed in both cases.

I started with

Lemma set_is_type :  Type = Set.
Proof.
reflexivity.

which gives an error message saying that Unable to unify "Set" with "Type@{Top.74}".

Then I tried

Lemma set_is_not_type : Type <> Set.
Proof.
intros contra.

At this point I do not know how to proceed. The tactic discriminate did not work, neither inversion contra.

Which one of the above two lemmas can be proved?

Body:
This actually isn't an entirely trivial theorem. To show that Type = Set results in a paradox (and hence that having separate levels of Type is necessary), you'll need to use a standard result akin to Russell's paradox from set theory. Specifically, you'll need Hurken's paradox, which essentially says that smaller Types can't be on equal footing to larger Types (remember that Type is polymorphic in Coq, and in particular, Set is the lowest level (or second lowest if you include Prop)).

The particular theorem we want can be found in the standard library.

Require Logic.Hurkens.
Import Logic.Hurkens.TypeNeqSmallType.

Check paradox.

paradox has the type signature forall A : Type, Type = A -> False. This is pretty much what we want to prove, since Set: Type (at least if Type is large enough).

Lemma set_is_not_type: Type <> Set.
Proof.
  intro F.
  exact (paradox _ F).
Defined.

Coq automatically sets restrictions on the Type in this lemma to ensure that Set: Type.

On the other hand, Set is equal to some level of Type, so we should be able to prove that Type = Set with some different constraints on this Type. The easiest way I found to do this was to prove that Type = Type, but then instantiate this theorem with Set. For whatever reason, as you found, reflexivity can't enforce universe constraints by itself. To do this, we need to make both the lemmas universe polymorphic so that they can be instantiated with a particular universe level.

Polymorphic Lemma type_is_type: Type = Type.
Proof.
  reflexivity.
Defined.

Polymorphic Lemma type_is_set: Type = Set.
Proof.
  apply type_is_type.
Defined.

The easier way to make everything universe polymorphic is to put Set Universe Polymorphism. before everything.


问:
Create SVG progress circle
Anyone know how to create a circle "progressbar" in svg? I need to specify the percentage of the circle, så that a color grows in the shape of a cake. </p>

<p>The growing can be static as long as I have a attribute to change its current status.  </p>

答:
Codepen-Link

```<code><div class="flex-wrapper">
  <div class="single-chart">
      <svg viewBox="0 0 36 36" class="circular-chart orange">
          <path class="circle-bg" d="M18 2.0845 a 15.9155 15.9155 0 0 1 0 31.831 a 15.9155 15.9155 0 0 1 0 -31.831" />
          <path class="circle" stroke-dasharray="30, 100" d="M18 2.0845 a 15.9155 15.9155 0 0 1 0 31.831 a 15.9155 15.9155 0 0 1 0 -31.831" />
          <text x="18" y="20.35" class="percentage">30%</text>
      </svg>
  </div>
</div>
</code>```

CSS Required for this svg circle

```<code>.flex-wrapper {
  display: flex;
  flex-flow: row nowrap;
}

.single-chart {
  width: 33%;
  justify-content: space-around ;
}

.circular-chart {
  display: block;
  margin: 10px auto;
  max-width: 80%;
  max-height: 250px;
}

.circle-bg {
  fill: none;
  stroke: #eee;
  stroke-width: 3.8;
}

.circle {
  fill: none;
  stroke-width: 2.8;
  stroke-linecap: round;
  animation: progress 1s ease-out forwards;
}

@keyframes progress {
  0% {
    stroke-dasharray: 0 100;
  }
}

.circular-chart.orange .circle {
  stroke: #ff9f00;
}

.percentage {
  fill: #666;
  font-family: sans-serif;
  font-size: 0.5em;
  text-anchor: middle;
}

a {
  font-size: 26px;
}
</code>```

.flex-wrapper {
  display: flex;
  flex-flow: row nowrap;
}

.single-chart {
  width: 33%;
  justify-content: space-around ;
}

.circular-chart {
  display: block;
  margin: 10px auto;
  max-width: 80%;
  max-height: 250px;
}

.circle-bg {
  fill: none;
  stroke: #eee;
  stroke-width: 3.8;
}

.circle {
  fill: none;
  stroke-width: 2.8;
  stroke-linecap: round;
  animation: progress 1s ease-out forwards;
}

@keyframes progress {
  0% {
    stroke-dasharray: 0 100;
  }
}

.circular-chart.orange .circle {
  stroke: #ff9f00;
}

.percentage {
  fill: #666;
  font-family: sans-serif;
  font-size: 0.5em;
  text-anchor: middle;
}

a {
  font-size: 26px;
}```
<pre class="snippet-code-html lang-html prettyprint-override"><code><div class="flex-wrapper">
  <div class="single-chart">
      <svg viewBox="0 0 36 36" class="circular-chart orange">
          <path class="circle-bg" d="M18 2.0845 a 15.9155 15.9155 0 0 1 0 31.831 a 15.9155 15.9155 0 0 1 0 -31.831" />
          <path class="circle" stroke-dasharray="30, 100" d="M18 2.0845 a 15.9155 15.9155 0 0 1 0 31.831 a 15.9155 15.9155 0 0 1 0 -31.831" />
          <text x="18" y="20.35" class="percentage">30%</text>
      </svg>
  </div>
</div>

<br>
<br>
<br>
<br>
<br>

Thanks to sergiopedercini</code>```

ContentLicense: CC BY-SA 2.5

Title: Create SVG progress circle

Body:
Anyone know how to create a circle "progressbar" in svg? I need to specify the percentage of the circle, så that a color grows in the shape of a cake.

The growing can be static as long as I have a attribute to change its current status.

Body:
Codepen-Link

<div class="flex-wrapper">
  <div class="single-chart">
      <svg viewBox="0 0 36 36" class="circular-chart orange">
          <path class="circle-bg" d="M18 2.0845 a 15.9155 15.9155 0 0 1 0 31.831 a 15.9155 15.9155 0 0 1 0 -31.831" />
          <path class="circle" stroke-dasharray="30, 100" d="M18 2.0845 a 15.9155 15.9155 0 0 1 0 31.831 a 15.9155 15.9155 0 0 1 0 -31.831" />
          <text x="18" y="20.35" class="percentage">30%</text>
      </svg>
  </div>
</div>

CSS Required for this svg circle

.flex-wrapper {
  display: flex;
  flex-flow: row nowrap;
}

.single-chart {
  width: 33%;
  justify-content: space-around ;
}

.circular-chart {
  display: block;
  margin: 10px auto;
  max-width: 80%;
  max-height: 250px;
}

.circle-bg {
  fill: none;
  stroke: #eee;
  stroke-width: 3.8;
}

.circle {
  fill: none;
  stroke-width: 2.8;
  stroke-linecap: round;
  animation: progress 1s ease-out forwards;
}

@keyframes progress {
  0% {
    stroke-dasharray: 0 100;
  }
}

.circular-chart.orange .circle {
  stroke: #ff9f00;
}

.percentage {
  fill: #666;
  font-family: sans-serif;
  font-size: 0.5em;
  text-anchor: middle;
}

a {
  font-size: 26px;
}

.flex-wrapper {
  display: flex;
  flex-flow: row nowrap;
}

.single-chart {
  width: 33%;
  justify-content: space-around ;
}

.circular-chart {
  display: block;
  margin: 10px auto;
  max-width: 80%;
  max-height: 250px;
}

.circle-bg {
  fill: none;
  stroke: #eee;
  stroke-width: 3.8;
}

.circle {
  fill: none;
  stroke-width: 2.8;
  stroke-linecap: round;
  animation: progress 1s ease-out forwards;
}

@keyframes progress {
  0% {
    stroke-dasharray: 0 100;
  }
}

.circular-chart.orange .circle {
  stroke: #ff9f00;
}

.percentage {
  fill: #666;
  font-family: sans-serif;
  font-size: 0.5em;
  text-anchor: middle;
}

a {
  font-size: 26px;
}

<div class="flex-wrapper">
  <div class="single-chart">
      <svg viewBox="0 0 36 36" class="circular-chart orange">
          <path class="circle-bg" d="M18 2.0845 a 15.9155 15.9155 0 0 1 0 31.831 a 15.9155 15.9155 0 0 1 0 -31.831" />
          <path class="circle" stroke-dasharray="30, 100" d="M18 2.0845 a 15.9155 15.9155 0 0 1 0 31.831 a 15.9155 15.9155 0 0 1 0 -31.831" />
          <text x="18" y="20.35" class="percentage">30%</text>
      </svg>
  </div>
</div>

<br>
<br>
<br>
<br>
<br>

<a href="https://codepen.io/sergiopedercini/">Thanks to sergiopedercini</a>


问:
Reading data from an excel file using PhpOffice\PhpSpreadsheet in symfony 4
I develop an application with symfony 4 and I need to read data from an excel file. I integrate PhpOffice \ PhpSpreadsheet in my project but I can not find documentation to use it for now. I find this site to start but it does not do everything I want. https://phpspreadsheet.readthedocs.io/en/latest/topics/reading-and-writing-to-file/

If someone would have another track or know how to read data from an excel file using PhpSpreadsheet.

```<code>public function excelReader(){

    $reader = new Xlsx();
    $reader->setReadDataOnly(TRUE);
    $spreadsheet = $reader->load("test.xlsx");
    $worksheet = $spreadsheet->getActiveSheet();

    $highestRow = $worksheet->getHighestRow();
    $highestColumn = $worksheet->getHighestColumn();
    $highestColumnIndex = \PhpOffice\PhpSpreadsheet\Cell\Coordinate::columnIndexFromString($highestColumn);
$res = array();
    for($row=1; $row < $highestRow ; $row++){
        for($col = 1; $col <= $highestColumnIndex; $col++){
            $value = $worksheet->getCellByColumnAndRow($col,$row)->getValue();
            array_push($res,$value);
        }
    }

    return $this->render('table/excel.html.twig', [
        'list' => $res,
    ]);

 }
</code>```

in this code I try to load and then read the test.xlsx file that I put in the controller folder. I get the following error: File "test.xlsx" does not exist.

答:
Try creating the folder {symfony folder}/public/uploads/ and put test.xlsx in that folder.
Then change this line in your code:
$spreadsheet = $reader->load("uploads/test.xlsx");
(The folder {symfony folder}/src/Controller/ is for code only for security reasons.)

There are examples of reading spreadsheets under
{symfony directory}/vendor/phpoffice/phpspreadsheet/samples/Reader/

Body:
I develop an application with symfony 4 and I need to read data from an excel file. I integrate PhpOffice \ PhpSpreadsheet in my project but I can not find documentation to use it for now. I find this site to start but it does not do everything I want. https://phpspreadsheet.readthedocs.io/en/latest/topics/reading-and-writing-to-file/

If someone would have another track or know how to read data from an excel file using PhpSpreadsheet.

public function excelReader(){

    $reader = new Xlsx();
    $reader->setReadDataOnly(TRUE);
    $spreadsheet = $reader->load("test.xlsx");
    $worksheet = $spreadsheet->getActiveSheet();

    $highestRow = $worksheet->getHighestRow();
    $highestColumn = $worksheet->getHighestColumn();
    $highestColumnIndex = \PhpOffice\PhpSpreadsheet\Cell\Coordinate::columnIndexFromString($highestColumn);
$res = array();
    for($row=1; $row < $highestRow ; $row++){
        for($col = 1; $col <= $highestColumnIndex; $col++){
            $value = $worksheet->getCellByColumnAndRow($col,$row)->getValue();
            array_push($res,$value);
        }
    }

    return $this->render('table/excel.html.twig', [
        'list' => $res,
    ]);

 }

in this code I try to load and then read the test.xlsx file that I put in the controller folder. I get the following error: File "test.xlsx" does not exist.