sql >> データベース >  >> RDS >> SQLite

sqliteデータベースに画像を挿入するにはどうすればよいですか?

    画像をbyte[]として抽出し、それを16進文字の文字列としてバイトに変換してから、その文字列を X'で囲みます。 your_hexadecimal_string '

    • 例: X'FFFEFDFCFBFA9........'の可能性があります

    その文字列をネイティブSQL経由で挿入する値として使用します

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

    または、SQliteDatbase挿入を使用することもできます 3番目のパラメーターとしてContentvaluesオブジェクトを受け取る便利なメソッド。

    の線に沿ってContentvaluesオブジェクトを設定します
    ContentValues cv = new Contentvalues();
    cv.put("Image",your_image_as_a_byte_array);
    db.insert("the_table_name",null,cv);
    

    ただし、画像の保存は面倒な場合があり、特に平均サイズが約10万を超える場合は、画像の保存はお勧めしません。

    画像が2Mに近いかそれを超える場合、CursorWindowには2Mの制限があるため、標準のAndroidSQLiteAPIを使用してその画像を取得することはできません。 1Mでも、CursorWindow内に1つの画像を取得できる可能性があります。

    推奨される方法は、画像へのパスまたはパスの一部を保存し、必要に応じてそのパスを介して画像を取得することです。

    (上記)と言うと、以下は、画像が100K未満の場合にデータベースに画像を保存するアプリです(public static final int MAX_FILE_SIZE = 100 * 1024; )またはパスを保存し、保存された内容に応じてパスまたはデータベースを介して画像を取得します。

    アプリには、画像の説明を含む2つのListViewがあります(右端には画像へのパスが含まれています)。いずれかのアイテムをクリックすると、画像が表示されます。

    例:

    100kを超える画像が多数あり、1つのfunny.pngは100k未満です:-

    この例では、画像はResフォルダーのRawフォルダーに配置されてから、data / data / files / imagesフォルダー(アプリのパッケージの名前を表します)にコピーされます。-

    DatabaseHelper、 DBHelper.java は:-

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

    呼び出しアクティビティMainActivity.java は:-

    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. SQLServerのテーブルで使用されているスペースを確認してください

    2. MySQLで日時から時間を差し引く方法は?

    3. 複数のデータベースに準拠したオンラインSQL構文チェッカー

    4. エラー「ORA-01789:クエリブロックの結果列の数が正しくありません」を修正しました