Android的副本数据库目录的问题? [英] Android copy database directory issue?

查看:110
本文介绍了Android的副本数据库目录的问题?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个需要访问资源文件夹数据库来获取数据时,应用程序启动,所以我是从资产的行动做一些复制数据的应用程序,但在过去的版本中,用户说不能打开应用程序,所以一些用户。

我可以知道,如果我需要将数据库从资产文件夹拷贝到用户设备,它的数据库目录路径,我应该用它来存储复制的数据库?或丢失我的$​​ C $ C一些重要的事情吗?

像现在这样,我只是在做这个设备上:

createDirectory:

 公共布尔createDirectory(){
    如果(Environment.getExternalStorageState()。包括(Environment.MEDIA_MOUNTED))
    {
        。字符串ROOTPATH​​ = Environment.getExternalStorageDirectory()getAbsolutePath()+ GlobalConfig.CONFIG_DATA_DIR;
        如果(isNeedDL(ROOTPATH​​)){
            文件MYDIR =新的文件(ROOTPATH​​);
            返回myDir.mkdirs();
        }
    }    返回false;
}

和数据库目录,其中GlobalConfig.CONFIG_DATA_DIR =/数据/

 路径= Environment.getExternalStorageDirectory()getAbsolutePath()+ GlobalConfig.CONFIG_DATA_DIR。

在SQLiteOpenHelper类:检查数据库退出,不要复制动作

 私人NOLDatabaseHelper(上下文的背景下,字符串路径){
    超(背景下,路径+ DB_NAME_OUTDBNAME,空,DB_VERSION);
    this.context =背景;
}公共无效的CreateDatabase(){    如果(!isDatabaseExited()){
        Log.v(GlobalConfig.TAG,没有数据库);
        getReadableDatabase();
        copyDataBaseFromAsset();
    }其他{
        Log.v(GlobalConfig.TAG,打开数据库);
    }
}公共静态布尔isDatabaseExited(){
    SQLiteDatabase CHECKDB = NULL;
    尝试{
        CHECKDB = SQLiteDatabase.openDatabase(DB_PATH + DB_NAME_OUTDBNAME,空,
                SQLiteDatabase.OPEN_READONLY);
        checkDB.close();        Log.v(GlobalConfig.TAG,检查?+ + DB_PATH + DB_NAME_OUTDBNAMECHECKDB:+ CHECKDB);
    }赶上(SQLiteException E){}    返回CHECKDB!= NULL?真假;
}

谢谢!

下面是拷贝功能:

  //修复数据库锁定问题
私人同步无效copyDataBaseFromAsset()
{
    INT长度= -1;
    字节[]缓冲区=新的字节[1024];
    AssetManager上午= context.getAssets();    尝试
    {
        InputStream的assetsDB = am.open(DB_NAME_INDBNAME);
        字符串outFileName = DB_PATH + DB_NAME_OUTDBNAME;
        的OutputStream DBOUT =新的FileOutputStream(outFileName);        而((长度= assetsDB.read(缓冲液))大于0){
            dbOut.write(缓冲液,0,长度);
        }        dbOut.flush();
        dbOut.close();
        assetsDB.close();    }赶上(例外五){
        Log.e(GlobalConfig.TAG,copyDataBaseFromAsset错误,是说:+ e.toString());
    }
}


解决方案

下面是一个工作code从资产文件夹复制数据库的数据目录:

 公共类DatabaseHelper扩展SQLiteOpenHelper {
// varaible声明
公共静态字符串标记=DatabaseHelper;
私人静态字符串DB_NAME =DMDatabase.sqlite;在资产//文件名
私人SQLiteDatabase sqliteDatabase;
私人最终上下文myContext;
私人字符串DatabasePath;公共DatabaseHelper(上下文的背景下){
    超级(上下文,DB_NAME,空,1);
    this.myContext =背景;
    DatabasePath =/数据/数据​​/+ myContext.getPackageName()
            +/数据库/;
}/ **
 *方法来创建内部应用程序的数据库
 *
 *引发IOException
 * /
公共无效的CreateDatabase()抛出IOException
    尝试{        //检查数据库是否存在
        布尔dbExist = checkDatabase();
        如果(!dbExist){
            //数据库不是present副本DATABSE
            this.getReadableDatabase();
            尝试{
                copyDatabse();
            }赶上(IOException异常五){
                // TODO:处理异常
                //串恩= e.getMessage();
                e.printStackTrace();
            }
        }
    }赶上(例外五){
        // TODO自动生成catch块
        e.printStackTrace();
    }
}/ **
 *检查是否已存在于数据库,以避免重新复制每个文件
 *一次打开应用程序。
 *
 *如果存在返回:真的,假的,如果它不
 * /
私人布尔checkDatabase(){
    SQLiteDatabase CHECKDB = NULL;
    尝试{
        CHECKDB = NULL;
        尝试{
            档案文件=新的文件(DatabasePath + DB_NAME);
            如果(file.exists()){
                CHECKDB = SQLiteDatabase.openDatabase(DatabasePath
                        + DB_NAME,空,SQLiteDatabase.OPEN_READONLY);
            }其他{
                返回false;
            }
        }赶上(的SQLException E){
            Log.d(DB异常,);
        }
        如果(CHECKDB!= NULL){
            checkDB.close();
        }
    }赶上(例外五){
        // TODO自动生成catch块
        e.printStackTrace();
    }
    返回CHECKDB!= NULL?真假;
}/ **
 *副本数据库从本地资产文件夹复制到刚创建
 *在系统文件夹,空数据库从那里可以访问和
 *处理。这是通过tranfering字节流进行。
 * * /
私人无效copyDatabse()抛出IOException
    尝试{
        //打开本地数据库的输入流
        InputStream的myInput = myContext.getAssets()开(DB_NAME)。
        //路径刚刚创建的空分贝
        字符串outFileName = DatabasePath + DB_NAME;
        //打开空分贝的输出流        的OutputStream myOutput =新的FileOutputStream(outFileName);
        //传递从inputfile中字节到OUTPUTFILE
        字节[]缓冲区=新的字节[1024 * 2];
        INT长;        而((长度= myInput.read(缓冲液))大于0){
            尝试{
                myOutput.write(缓冲液,0,长度);
            }赶上(例外五){
            }
        }
        myOutput.flush();
        myOutput.close();
        myInput.close();
    }赶上(例外五){
        // TODO自动生成catch块
        e.printStackTrace();
    }
}@覆盖
公共无效的onCreate(SQLiteDatabase DB){
    // TODO自动生成方法存根
    的CreateDatabase();
}@覆盖
公共无效onUpgrade(SQLiteDatabase分贝,INT oldVersion,诠释静态网页){
    // TODO自动生成方法存根}/ **
 *其他方法来插入,删除,更新,选择数据库
 * /}

我希望能对你有所帮助。


  

但是不建议过程,从资产数据目录复制数据库。一旦创建了数据库,的onCreate 方法将被调用,你应该使用查询来创建表并插入默认数据到数据库中。


I have a application which need to access assets folder database to get data when application start, so I doing some copy data from assets action, but in last release, user say that cannot open the application, so some user can.

May I know, if I need to copy a database from assets folder to user device, which database directory path should I use to store the copied database? or missing some important thing in my code?

as now, I just doing this on device:

createDirectory:

public boolean createDirectory() {  
    if(Environment.getExternalStorageState().contains(Environment.MEDIA_MOUNTED)) 
    {
        String rootPath = Environment.getExternalStorageDirectory().getAbsolutePath()+GlobalConfig.CONFIG_DATA_DIR;
        if( isNeedDL( rootPath )) {
            File myDir = new File(rootPath);
            return myDir.mkdirs();
        }
    }

    return false;
}

and database directory, which GlobalConfig.CONFIG_DATA_DIR = "/data/"

path = Environment.getExternalStorageDirectory().getAbsolutePath()+GlobalConfig.CONFIG_DATA_DIR;

and in SQLiteOpenHelper class: check if database exited, do copy action.

private NOLDatabaseHelper(Context context, String path) {
    super(context, path + DB_NAME_OUTDBNAME, null, DB_VERSION);
    this.context = context;
}   

public void createDatabase() {

    if(!isDatabaseExited()) {
        Log.v(GlobalConfig.TAG, "NO database");
        getReadableDatabase();
        copyDataBaseFromAsset();
    } else {
        Log.v(GlobalConfig.TAG, "Has database");
    }
}

public static boolean isDatabaseExited() {
    SQLiteDatabase checkDB = null;
    try {
        checkDB = SQLiteDatabase.openDatabase( DB_PATH + DB_NAME_OUTDBNAME, null,
                SQLiteDatabase.OPEN_READONLY);
        checkDB.close();

        Log.v(GlobalConfig.TAG,"check? "+DB_PATH + DB_NAME_OUTDBNAME+" checkDB:"+checkDB);
    } catch (SQLiteException e) {}

    return checkDB != null ? true : false;
}

Thanks!

Here is copy function:

// to fix database is locked issue
private synchronized void copyDataBaseFromAsset() 
{
    int length                  = -1;
    byte[] buffer               = new byte[1024];
    AssetManager am             = context.getAssets();

    try 
    {
        InputStream assetsDB    = am.open(DB_NAME_INDBNAME);
        String outFileName      = DB_PATH + DB_NAME_OUTDBNAME;
        OutputStream dbOut      = new FileOutputStream(outFileName);

        while ((length = assetsDB.read(buffer)) > 0) {
            dbOut.write(buffer, 0, length);
        }

        dbOut.flush();
        dbOut.close();
        assetsDB.close();

    } catch(Exception e) {
        Log.e( GlobalConfig.TAG, "copyDataBaseFromAsset error, is say: "+e.toString() );
    }
}

解决方案

below is a working code for copying database from assets folder to data directory:

public class DatabaseHelper extends SQLiteOpenHelper {
// varaible declaration
public static String TAG = "DatabaseHelper";
private static String DB_NAME = "DMDatabase.sqlite";//file name in assets
private SQLiteDatabase sqliteDatabase;
private final Context myContext;
private String DatabasePath;

public DatabaseHelper(Context context) {
    super(context, DB_NAME, null, 1);
    this.myContext = context;
    DatabasePath = "/data/data/" + myContext.getPackageName()
            + "/databases/";
}

/**
 * Method to create the database inside application
 * 
 * @throws IOException
 */
public void createDatabase() throws IOException {
    try {

        // check if the database exists
        boolean dbExist = checkDatabase();
        if (!dbExist) {
            // database is not present copy databse
            this.getReadableDatabase();
            try {
                copyDatabse();
            } catch (IOException e) {
                // TODO: handle exception
                // String ex = e.getMessage();
                e.printStackTrace();
            }
        }
    } catch (Exception e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
}

/**
 * Check if the database already exist to avoid re-copying the file each
 * time you open the application.
 * 
 * @return true if it exists, false if it doesn't
 */
private boolean checkDatabase() {
    SQLiteDatabase checkDB = null;
    try {
        checkDB = null;
        try {
            File file = new File(DatabasePath + DB_NAME);
            if (file.exists()) {
                checkDB = SQLiteDatabase.openDatabase(DatabasePath
                        + DB_NAME, null, SQLiteDatabase.OPEN_READONLY);
            } else {
                return false;
            }
        } catch (SQLException e) {
            Log.d("DB Exception", "");
        }
        if (checkDB != null) {
            checkDB.close();
        }
    } catch (Exception e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
    return checkDB != null ? true : false;
}

/**
 * Copies your database from your local assets-folder to the just created
 * empty database in the system folder, from where it can be accessed and
 * handled. This is done by tranfering bytestream.
 * */
private void copyDatabse() throws IOException {
    try {
        // Open your local db as the input stream
        InputStream myInput = myContext.getAssets().open(DB_NAME);
        // Path to the just created empty db
        String outFileName = DatabasePath + DB_NAME;
        // Open the empty db as the output stream

        OutputStream myOutput = new FileOutputStream(outFileName);
        // transfer bytes from the inputfile to the outputfile
        byte[] buffer = new byte[1024 * 2];
        int length;

        while ((length = myInput.read(buffer)) > 0) {
            try {
                myOutput.write(buffer, 0, length);
            } catch (Exception e) {
            }
        }
        myOutput.flush();
        myOutput.close();
        myInput.close();
    } catch (Exception e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
}



@Override
public void onCreate(SQLiteDatabase db) {
    // TODO Auto-generated method stub
    createDatabase();
}

@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
    // TODO Auto-generated method stub

}

/**
 * Other Methods to insert,delete, update,select in Database
 */

}

I hope will be helpful for you.

But it is not recommended process to copy database from assets from data directory. Once the database on created, onCreate method will be called in which you should use queries to create tables and insert default data into database.

这篇关于Android的副本数据库目录的问题?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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