sql >> Database >  >> RDS >> SQLite

Hoe kan ik een afbeelding in een sqlite-database invoegen?

Je extraheert de afbeelding als een byte[] en converteert die vervolgens naar de bytes, als een reeks hexadecimale tekens en sluit die reeks vervolgens in X' uw_hexadecimal_string '

  • bijv. het zou kunnen zijn X'FFFEFDFCFBFA9........'

en gebruik die string als de waarde om in te voegen via native SQL

  • bijv. INSERT INTO your_table (image_column) VALUES(X'FFFEFDFCFBFA9........')

Of u kunt de SQliteDatbase insert . gebruiken gemaksmethode, die een Contentvalues-object als de 3e parameter neemt. Je zou het Contentvalues-object zoiets instellen als

ContentValues cv = new Contentvalues();
cv.put("Image",your_image_as_a_byte_array);
db.insert("the_table_name",null,cv);

Het opslaan van afbeeldingen kan echter lastig zijn en het wordt niet aanbevolen om afbeeldingen op te slaan, vooral niet als ze gemiddeld meer dan 100k groot zijn.

Als een afbeelding dichtbij of groter is dan 2M, kunt u die afbeelding niet ophalen met de standaard Android SQLite API, aangezien een CursorWindow een limiet van 2M heeft. Zelfs bij 1M zou je misschien 1 afbeelding binnen een CursorWindow kunnen krijgen.

De aanbevolen methode is om het pad of een deel van het pad naar de afbeelding op te slaan en indien nodig de afbeelding via het pad op te halen.

Voorbeeld

Dat gezegd hebbende (het bovenstaande), is het volgende een app die de afbeelding in de database opslaat als deze lager is dan 100K (public static final int MAX_FILE_SIZE = 100 * 1024; ) of sla het pad op en haal de afbeelding op via het pad of de database volgens wat is opgeslagen.

De app heeft twee lijstweergaven met beschrijvingen van de afbeeldingen (de meest rechtse bevat het pad naar de afbeelding). Als u op een item in een van beide klikt, wordt de afbeelding weergegeven.

bijv.

Er zijn een aantal afbeeldingen waarvan de meeste meer dan 100k zijn, één funny.png is minder dan 100k :-

De afbeeldingen zijn voor dit voorbeeld in de Raw-map van de Res-map geplaatst, ze worden vervolgens gekopieerd naar de map data/data/files/images (waar staat voor de naam van het pakket van de app):-

De DatabaseHelper, DBHelper.java is:-

public class DBHelper extends SQLiteOpenHelper {
    public static final String DBNAME = "images.db";
    public static final int DBVERSION = 1;

    // The maximum size of an image that should be stored 100K
    public static final int MAX_FILE_SIZE = 100 * 1024;

    public static final String TB_IMAGE = "image";
    public static final String COL_IMAGE_ID = BaseColumns._ID;
    public static final String COL_IMAGE_PATH = "image_path";
    public static final String COL_IMAGE_NAME = "image_name";
    public static final String COl_IMAGE_DESCRIPTION = "image_description";
    public static final String COL_IMAGE_SIZE = "image_size";
    public static final String COL_IMAGE_IMAGE = "image";

    SQLiteDatabase mDB;

    /**
     * Construct DBHelper, note that it will open the database and
     * thus create it if it doesn't exist
     * @param context   a context from the invoking activity
     */
    public DBHelper(Context context) {
        super(context, DBNAME, null, DBVERSION);
        mDB = this.getWritableDatabase();
    }

    /**
     * Create the table(s)
     * @param db
     */
    @Override
    public void onCreate(SQLiteDatabase db) {
        String crtsql = "CREATE TABLE IF NOT EXISTS " + TB_IMAGE +
                "(" +
                COL_IMAGE_ID + " INTEGER PRIMARY KEY, " +
                COL_IMAGE_PATH + " TEXT UNIQUE, " +
                COL_IMAGE_NAME + " TEXT, " +
                COl_IMAGE_DESCRIPTION + " TEXT, " +
                COL_IMAGE_SIZE + " INTEGER, " +
                COL_IMAGE_IMAGE + " BLOB DEFAULT x'00'" +
                ")";
        db.execSQL(crtsql);
    }

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

    }

    /**
     * Return a Cursor with all the rows from the image table
     * @return  The Cursor
     */
    public Cursor getImageList() {
        return mDB.query(TB_IMAGE,null,null,null,null,null,null);
    }


    /**
     * Store an image row in the image table, noting that is the image
     *  size is small than the max size that the image will be stored as a blob
     *  otherwise a blob of 1 byte is stored due to the default value.
     * @param path          the path to the image
     * @param description   a description for the image
     * @return              the id (rowid) of the row
     */
    public long addImageFromPath(String path, String description) {

        ContentValues cv = new ContentValues();
        File f = new File(path);
        InputStream is;

        // If the file doesn't exist don't store a row
        if (!f.exists()) {
            return -1;
        }

        // Always store the name, description, path and size
        cv.put(COL_IMAGE_NAME,f.getName());
        cv.put(COl_IMAGE_DESCRIPTION,description);
        cv.put(COL_IMAGE_SIZE,f.length());
        cv.put(COL_IMAGE_PATH,f.getAbsolutePath());

        // If the size is less than the max then get the filestream
        // and convert to a byte[].
        // Note if larger then the max file size the default x'00' blob
        // will be applied
        if (f.length() < MAX_FILE_SIZE) {
            byte[] buffer = new byte[(int) f.length()];
            try {
                is = new FileInputStream(f);
                is.read(buffer);
            } catch (IOException e) {
                e.printStackTrace();
                return -1;
            }
            cv.put(COL_IMAGE_IMAGE,buffer);
        }
        // Do the insert
        return mDB.insert(TB_IMAGE,null,cv);
    }

    /**
     * get the image as a bitmap from the DB if stored, otherwise get it from
     * the file, according to the id.
     * @param id    the id of the row in the image table
     * @return      the bitmap to be returned (note may be empty bitmap)
     */
    public Bitmap getImage(long id) {
        byte[] ba = new byte[0];

        // If the image is stored in the DB then extract and return the bitmap
        if (isStoredAsImage(id)) {
            return getImageAsBitMap(id);
        }
        // If not then get the respective row from the DB
        Cursor csr = mDB.query(
                TB_IMAGE,
                null,
                COL_IMAGE_ID+"=?",
                new String[]{String.valueOf(id)},
                null,
                null,
                null
        );

        // Prepare to convert the path to a file
        String path = ""; //<<<< default to  empty path
        File f = new File(path); //<<< default to empty file
        // If a valid row was found get the path and File from the row
        if (csr.moveToFirst()) {
            path = csr.getString(csr.getColumnIndex(COL_IMAGE_PATH));
            f = new File(path);
        }
        // done with the cursor so close it
        csr.close();

        // If the file exists then return the Bitmap
        if (f.exists()) {
            return BitmapFactory.decodeFile(f.getAbsolutePath());
        }
        // return an empty bitmap
        return BitmapFactory.decodeByteArray(ba,0,ba.length);
    }

    /**
     * Check to see if an image is stored in the DB,
     *  note assumes anything less than 8 bytes isn't an image
     * @param id    the id of the row in the image table
     * @return      true if like an image is stored, otherwise false
     */
    private boolean isStoredAsImage(long id) {
        boolean rv = true;
        byte[] ba = new byte[0];

        // Get the respective row from the image table
        Cursor csr = mDB.query(
                TB_IMAGE,
                null,
                COL_IMAGE_ID+"=?",
                new String[]{String.valueOf(id)},
                null,
                null,
                null
        );

        // If a row was found get the blob into byte array ba
        // if not then ready to return false
        if (csr.moveToFirst()) {
            ba = csr.getBlob(csr.getColumnIndex(COL_IMAGE_IMAGE));
        } else {
            rv = false;
        }
        // If the byte array ba is less then 8 bytes then ready to return false
        if (ba == null || ba.length < 8) {
            rv =  false;
        }
        // done with the Cursor so close it
        csr.close();
        // return the result
        return rv;
    }

    /**
     * get the image (assumes isStoredAsImage is used prior to invocation)
     * @param id    the id of the respective row
     * @return      the bitmap (may be 0 length)
     */
    private Bitmap getImageAsBitMap(long id) {
        byte[] ba = new byte[0];
        Bitmap bmp;
        Cursor csr =mDB.query(
                TB_IMAGE,
                null,
                COL_IMAGE_ID+"=?",
                new String[]{String.valueOf(id)},
                null,
                null,
                null
        );
        if (csr.moveToFirst()) {
            ba = csr.getBlob(csr.getColumnIndex(COL_IMAGE_IMAGE));
        }
        csr.close();
        return BitmapFactory.decodeByteArray(ba,0,ba.length);
    }
} 

De activiteit Aanroepen MainActivity.java is:-

public class MainActivity extends AppCompatActivity {

    public static final String IMAGES_DIRECTORY = "images";
    private static File images_file;

    ArrayAdapter<String> mAdapter;
    ListView mListView01, mListView02;
    ArrayList<String> mImages;
    CursorAdapter mCsrAdapter;
    Cursor mCsr;
    ImageView mImageView;
    DBHelper mDBHlpr;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        // get the View/Viewgroup IDs
        mListView01 = this.findViewById(R.id.listview001); // File List
        mListView02 = this.findViewById(R.id.listview002); // DB List
        mImageView = this.findViewById(R.id.imageview001); // Image display

        // get an instance of the DBHelper
        mDBHlpr = new DBHelper(this);

        // Copy images from raw folder to data/data/<package>/Files/images
        // Also store all the images in the Database (or not depedning upon size)
        getImagesFile(this);
        if (getImagesCount() < 1) {
            loadRawImages();
            storeImagesToDB();
        }
        // Setup the two ListViews to display image name lists
        displayList();
        displayListFromDB();

        // setup the file list so that when an item is clicked the image is displayed
        mListView01.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
                String imagename = mListView01.getItemAtPosition(i).toString();
                displayImage(imagename);
            }
        });

        // setup the DB list so that when an item is clicked the image is displayed
        mListView02.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
                displayDBImage(l);
            }
        });
    }

    /**
     * Store the images in the images folder to the DB giving then a calculated description
     * e.g. image1, image2 .....
     */
    private void storeImagesToDB() {
        File f = getImagesFile(this);
        File[] images = f.listFiles();
        int imagecounter = 1;
        for (File img: images) {
            mDBHlpr.addImageFromPath(img.getPath(),"image" + String.valueOf(imagecounter++));
        }
    }

    /**
     * return the directory/folder where the images are stored as a File
     * @param context   a valid context
     * @return          the number of images
     */
    public static File getImagesFile(Context context) {
        if (images_file == null) {
            images_file = new File(context.getFilesDir().getPath() + File.separator + IMAGES_DIRECTORY);
            if (!images_file.exists()) {
                images_file.mkdirs();
            }
        }
        return images_file;
    }

    /**
     * get the number of images
     * @return the number of images
     */
    public static long getImagesCount() {
        File[] files = images_file.listFiles(new FileFilter() {
            @Override
            public boolean accept(File file) {
                return file.isFile();
            }
        });
        return (long) files.length;
    }

    /**
     * Setup/refresh the list of images according to the images folder
     * (left ListView)
     */
    private void displayList() {
        if (mImages == null) {
            mImages = new ArrayList<>();
        } else {
            mImages.clear();
        }
        mImages.addAll(Arrays.asList(images_file.list()));
        if (mAdapter == null) {
            mAdapter = new ArrayAdapter<String>(this,android.R.layout.simple_list_item_1, mImages);
            mListView01.setAdapter(mAdapter);
        } else {
            mAdapter.notifyDataSetChanged();
        }
    }

    /**
     * Set the image view according to the file
     * @param imageName the name of the image (as per the ListView)
     */
    private void displayImage(String imageName) {
        File img = new File(images_file.getPath() + File.separator + imageName);
        if (img.exists()) {
            Bitmap bmp = BitmapFactory.decodeFile(img.getAbsolutePath());
            mImageView.setImageBitmap(bmp);
        }
    }

    /**
     * Set the image view according to the image stored/referred to by the DB
     * @param id    the id of the respective row in the image table
     */
    private void displayDBImage(long id) {
        mImageView.setImageBitmap(mDBHlpr.getImage(id));
    }

    /**
     * Setup/refresh the list of images as obtained from the DB (right listview)
     */
    private void displayListFromDB() {
        mCsr = mDBHlpr.getImageList();
        if (mCsrAdapter == null) {
            mCsrAdapter = new SimpleCursorAdapter(
                    this,
                    android.R.layout.simple_list_item_2,
                    mCsr,
                    new String[]{DBHelper.COL_IMAGE_NAME,DBHelper.COL_IMAGE_PATH},
                    new int[]{android.R.id.text1,android.R.id.text2},
                    0
            );
            mListView02.setAdapter(mCsrAdapter);
        } else {
            mCsrAdapter.swapCursor(mCsr);
        }
    }

    /**
     * Load (copy from raw folder to images folder) all images
     */
    private void loadRawImages() {
        Field[] fields = R.raw.class.getFields();
        int resourceID = 0;
        String resourceName;
        for (Field fld: fields) {
            resourceName = fld.getName();
            try {
                resourceID = fld.getInt(fld);
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
            Log.d("RAW FLDINFO","name=" + fld.getName() + " ID=" + String.valueOf(resourceID));
            copyResourceImageToImages(resourceID,resourceName, true);
        }
    }

    /**
     * Copy an image from the raw directory (app/src/main/res/raw directory) to
     *  the Apps data/data/files/images folder
     * @param resourceID        ID of the resource
     * @param resourceName      name of the resource (file name less extension)
     * @param throw_exception   true if an exception should be thrown
     */
    private void copyResourceImageToImages(int resourceID, String resourceName, boolean throw_exception) {
        String tag = "CPYRSRCTOIMAGES";
        InputStream is = getResources().openRawResource(resourceID);
        File of = new File(images_file.getPath() + File.separator + resourceName + ".jpg");
        Log.d(tag,"Initiating Copy of File " + of.getName());
        int buffer_size = 1024 * 4;
        int bytesread = 0;
        long bytescopied = 0;
        OutputStream os;
        byte[] buffer = new byte[buffer_size];
        if (!of.exists()) {
            try {
                of.createNewFile();
            } catch (IOException e) {
                Log.d(tag,"Error Creating File " + of.getName());
                e.printStackTrace();
                if (throw_exception) {
                    throw new RuntimeException("Error Creating Output File" + of.getName());
                }
                return;
            }
        }
        try {
            os = new FileOutputStream(of);
        } catch (IOException e) {
            Log.d(tag,"Error Creating OutputStream for File " + of.getName());
            e.printStackTrace();
            if (throw_exception) {
                throw new RuntimeException("Error Creating OutputStream for File " + of.getName());
            }
            return;
        }
        if (os == null) {
            throw new RuntimeException("OutputStream not initialised.");
        }
        try {
            while ((bytesread = is.read(buffer)) > 0 ){
                try {
                    os.write(buffer, 0, bytesread);
                } catch (IOException e) {
                    String msg = "Error Writing to Output File " + of.getName() + " Bytes Copied = " + bytescopied;
                    Log.d(tag, msg);
                    e.printStackTrace();
                    if (throw_exception) {
                        os.close();
                        of.delete();
                        throw new RuntimeException(msg);
                    }
                    is.close();
                    os.close();
                    of.delete();
                    return;
                }
                bytescopied = bytescopied + bytesread;
            }
        }catch (IOException e) {
            String msg = "Error reading Input File " + resourceName + " Bytes Copied = " + bytescopied;
            Log.d(tag,"Error Reading Input File " + resourceName);
            e.printStackTrace();
            if (throw_exception) {
                throw new RuntimeException(msg);
            }
            try {
                is.close();
                os.close();
                of.delete();
            } catch (IOException e2) {
                e2.printStackTrace();
            }
        }
        Log.d(tag,"File " + of.getName() +" Copied - Bytes Successfully Copied = " + bytescopied);
        try {
            os.flush();

        } catch (IOException e) {
            e.printStackTrace();
        }

        try {
            os.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        try {
            is.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}


  1. Ongeldig parameternummer:parameter is niet gedefinieerd Gegevens invoegen

  2. Kolomrechten verkrijgen voor een tabel in SQL Server met T-SQL:sp_column_privileges

  3. MySQL installeren en configureren op Ubuntu 20.04

  4. Een offline app voor internationalisering maken:gebruik Sqlite-database