如何将视频内容存储在SQLite数据库中(而不是视频路径) [英] How to store video content in SQLite database (not the video path)

查看:532
本文介绍了如何将视频内容存储在SQLite数据库中(而不是视频路径)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想将视频存储在sqlite数据库中. P.S.我不想存储路径,但要存储实际的视频内容. 我已经将视频转换为字节数组,并将字节数组存储在sqlite数据库中.在检索时,字节数组被转换为File.但是视频没有播放.请帮忙.

I want to store a video in sqlite database. P.S. I do not want to store the path but the actual video contents. I have converted the video in byte array and stored byte array in sqlite database. Upon retrieval bytearray is being converted into File. But video is not playing. Please help.

推荐答案

我想将视频存储在sqlite数据库中. P.S.我不想 存储路径,但存储实际的视频内容.

I want to store a video in sqlite database. P.S. I do not want to store the path but the actual video contents.

除非视频非常短且占用很少的空间(例如每个视频最多占用20万,可能是1/10秒,但要取决于保存的格式),否则您可能会遇到问题和异常/崩溃.

Unless the videos are very short and take up little space (say up to 200k each, perhaps 1/10th of a second but would depend upon the format it is saved in) then you would likely encounter issues and exceptions/crashes.

  • 使用一部手机大约2秒钟黑色会占用2.2Mb,而实际录制视频2秒钟会占用7Mb.

尽管SQLite能够按照:-

Although SQLite has the ability to store relative large BLOB's as per :-

字符串或BLOB的最大长度

Maximum length of a string or BLOB

在SQLite中定义字符串或BLOB中的最大字节数 通过预处理程序宏SQLITE_MAX_LENGTH.这个的默认值 宏为10亿(10亿或10亿).你可以 使用命令行选项在编译时提高或降低此值 像这样:

The maximum number of bytes in a string or BLOB in SQLite is defined by the preprocessor macro SQLITE_MAX_LENGTH. The default value of this macro is 1 billion (1 thousand million or 1,000,000,000). You can raise or lower this value at compile-time using a command-line option like this:

-DSQLITE_MAX_LENGTH = 123456789当前实现仅支持最大231-1或2147483647的字符串或BLOB长度. 诸如hex()之类的内置函数可能会在此之前失效.在 对安全敏感的应用程序,最好不要尝试增加 最大字符串和Blob长度.实际上,您可能会做得更好,降低 最大字符串长度和blob长度在a的范围内 如果可能的话,几百万.

-DSQLITE_MAX_LENGTH=123456789 The current implementation will only support a string or BLOB length up to 231-1 or 2147483647. And some built-in functions such as hex() might fail well before that point. In security-sensitive applications it is best not to try to increase the maximum string and blob length. In fact, you might do well to lower the maximum string and blob length to something more in the range of a few million if that is possible.

在SQLite的INSERT和SELECT处理的一部分中,完整的 数据库中每一行的内容被编码为单个BLOB.所以 SQLITE_MAX_LENGTH参数还确定 连续字节.

During part of SQLite's INSERT and SELECT processing, the complete content of each row in the database is encoded as a single BLOB. So the SQLITE_MAX_LENGTH parameter also determines the maximum number of bytes in a row.

可以使用以下命令在运行时降低最大字符串或BLOB长度 sqlite3_limit(db,SQLITE_LIMIT_LENGTH,size)接口. SQLite中的限制

The maximum string or BLOB length can be lowered at run-time using the sqlite3_limit(db,SQLITE_LIMIT_LENGTH,size) interface. Limits In SQLite

Android SDK的 CursorWindow 的限制为2Mb,如果有缓冲区,则该限制适用于该行的所有列.这样,即使您可以成功存储视频,也可能无法检索这些视频.

The Android SDK's CursorWindow has a limitation of 2Mb and that is for all the columns of the row(s) if buffers. As such even if you can store Videos successfully, you may not be able to retrieve those Videos.

推荐的方式是您不需要的方式,即存储视频的路径.

如果我将视频存储在内部/外部存储中并存储 路径而不是然后我将如何能够从一些访问相同 其他设备.

If i store the video in my internal/external storage and store the path instead then how will i be able to access the same from some other device.

您将遇到与数据库相同的问题,因为它通常存储在受保护的应用程序"数据中.除非该数据库是预先存在的数据库(即已填充数据),否则在这种情况下,该数据库将通过APK与App一起分发.

You would have the same issue with the database as it's typically stored within the Applications data which is protected. That is unless the database is a pre-existing database (i.e. populated with data), in which case the database is distributed with the App via the APK.

如果后者是通过APK分发的预先存在的数据库,那么视频也可以作为APK的一部分分发,因此可以像数据库一样受到保护和暴露.

If the latter, a pre-existing database distributed via the APK, then the videos can also be distributed as part of the APK and hence as protected as and as exposable as the database.

如果您打算在不属于APK的设备之间分发视频,则SQlite可能不是正确的解决方案,因为它是嵌入式数据库,并且没有内置的客户端/服务器功能.

If your intention is to distribute videos between devices that are not part of the APK then SQlite is probably not the correct solution as it's an embedded database and has no client/server functionality built in.

如果我的设备格式化了,那我将丢失所有 数据.

Besides what if my device gets formatted then I will lose all the data.

在这种情况下,数据库将像其他任何数据一样易受攻击,因为数据库就是一个文件,就像视频,Word文档等一样,它们都需要一个适合查看/更改内容的应用程序.但是,如果数据库是预先存在的数据库,则只需重新安装该应用程序即可从APK恢复数据库和其他文件.

In such a scenario, the database would be as vulnerable as any other data, as that is all the database is, a file, just like a video, a word document etc which all need a suitable application to view/change the content. However, if the database is a pre-existing database, then simply re-installing the App would restore the database and other files from the APK.

在创建新项目后,按照以下步骤下载了4个视频并将其复制到res/raw文件夹中(在创建原始文件夹之后):-

After creating new project 4 videos were downloaded and copied into the res/raw folder (after creating the raw folder) as per :-

为2列表创建了数据库帮助器(SQLiteOpenHelper的子类),并带有 - _id 列(名为 _id 的注释,用于SimpleCursorAdapter ). -video_path用于存储视频的路径/名称(不是完整路径,但足以从存储的数据中确定路径) -请注意,UNIQUE已编码为停止添加重复项.

The Database Helper (subclass of SQLiteOpenHelper) was created for a 2 column table an with - _id column (note named _id for use with SimpleCursorAdapter). - video_path for storing the path/name of the video (not the full path but sufficient to be able to determine the path from the data stored) - Note UNIQUE has been coded to stop duplicates being added.

使用一些基本方法允许添加和删除行以及提取所有行(通过与SimpleCursorAdapter配合使用的Cursor).

With some basic method to allow rows to be added and deleted and for all rows to be extracted (via a Cursor for use with the SimpleCursorAdapter).

public class DBHelper extends SQLiteOpenHelper {

    public static final String DBNAME = "myvideos";
    public static final int DBVERSION = 1;

    public static final String TBL_VIDEO = "video";

    public static final String COL_VIDEO_ID = BaseColumns._ID;
    public static final String COL_VIDEO_PATH = "video_path";


    SQLiteDatabase mDB;

    public DBHelper(Context context) {
        super(context, DBNAME, null, DBVERSION);
        mDB = this.getWritableDatabase();
    }


    @Override
    public void onCreate(SQLiteDatabase db) {

        String crt_video_table = "CREATE TABLE IF NOT EXISTS " + TBL_VIDEO + "(" +
                COL_VIDEO_ID + " INTEGER PRIMARY KEY," +
                COL_VIDEO_PATH + " TEXT UNIQUE" +
                ")";
        db.execSQL(crt_video_table);
    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {

    }

    public long addVideo(String path) {
        ContentValues cv = new ContentValues();
        cv.put(COL_VIDEO_PATH,path);
        return mDB.insert(TBL_VIDEO,null,cv);
    }

    public Cursor getVideos() {
        return mDB.query(TBL_VIDEO,null,null,null,null,null,null);
    }

    public int deleteVideoFromDB(long id) {
        String whereclause = COL_VIDEO_ID + "=?";
        String[] whereargs = new String[]{String.valueOf(id)};
        return mDB.delete(TBL_VIDEO,whereclause,whereargs);
    }
}

漂亮的 MainActivity.java (请参阅注释)

public class MainActivity extends AppCompatActivity {

    TextView mMyTextView;
    ListView mVideoList;
    VideoView mVideoViewer;
    DBHelper mDBHlpr;
    Cursor mCsr;
    SimpleCursorAdapter mSCA;

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

        mMyTextView =  this.findViewById(R.id.mytext);
        mVideoList = this.findViewById(R.id.videolist);
        mVideoViewer = this.findViewById(R.id.videoviewer);

        mDBHlpr = new DBHelper(this);
        addVideosFromRawResourceToDB();
    }

    @Override
    protected void onDestroy() {
        mCsr.close(); //<<<<<<<<<< clear up the Cursor
        super.onDestroy();
    }

    @Override
    protected void onResume() {
        super.onResume();
        manageListView(); //<<<<<<<<<< rebuild and redisplay the List of Videos (in case they have changed) 
    }

    /**
     *  Setup or Refresh the ListView adding the OnItemClick and OnItemLongClick listeners
     */
    private void manageListView() {
        mCsr = mDBHlpr.getVideos();

        // Not setup so set it up
        if (mSCA == null) {
            // Instantiate the SimpleCursorAdapter
            mSCA = new SimpleCursorAdapter(
                    this,
                    android.R.layout.simple_list_item_1, // Use stock layout
                    mCsr, // The Cursor with the list of videos
                    new String[]{DBHelper.COL_VIDEO_PATH}, // the column (columns)
                    new int[]{android.R.id.text1}, // the view id(s) into which the column(s) data will be placed
                    0 
            );
            mVideoList.setAdapter(mSCA); // Set the adpater for the ListView
            /**
             * Add The Long Click Listener (will delete the video row from the DB (NOT the video))
             */
            mVideoList.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
                @Override
                public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
                    mDBHlpr.deleteVideoFromDB(id);
                    manageListView(); // <<<<<<<<<< refresh the ListView as data has changed
                    return true;
                }
            });
            /**
             * Play the respective video when the item is clicked
             * Note Cursor should be at the correct position so data can be extracted directly from the Cursor
             */
            mVideoList.setOnItemClickListener(new AdapterView.OnItemClickListener() {
                @Override
                public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                    setCurrentVideo(mCsr.getString(mCsr.getColumnIndex(DBHelper.COL_VIDEO_PATH)));
                }
            });
        } else {
            mSCA.swapCursor(mCsr); //<<<<<<<<<< apply the changed Cursor
        }
    }

    /**
     * Set the currrent video and play it
     * @param path the path (resource name of the video)
     */
    private void setCurrentVideo(String path) {

        mVideoViewer.setVideoURI(
                Uri.parse(
                       "android.resource://" + getPackageName() + "/" + String.valueOf(
                               getResources().getIdentifier(
                                       path,
                               "raw",
                               getPackageName())
                       )
                )
        );
        mVideoViewer.start();
    }

    /**
     *  Look at all the resources in the res/raw folder and add the to the DB (not if they are duplicates due to UNQIUE)
     */
    private void addVideosFromRawResourceToDB() {
            Field[] fields=R.raw.class.getFields();
            for(int count=0; count < fields.length; count++){
                Log.i("Raw Asset: ", fields[count].getName());
                mDBHlpr.addVideo(fields[count].getName());
            }
    }
}

结果

第一次开始(什么都没玩):-

Results

When first started (nothing plays) :-

这篇关于如何将视频内容存储在SQLite数据库中(而不是视频路径)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆