无法从资产中复制SQLite数据库

时间:2011-11-08 14:50:09

标签: java android sqlite

我尝试从资产目录复制SQLite数据库以便以后访问它。但我做不到!

public class DatabaseAdapter {
    private static String DB_PATH = "/data/data/com.mypackage/databases/";
    private static String DB_NAME = "database.sqlite";
    private static String TABLE_NAME = "content_table";

    private SQLiteDatabase database = null;
    private final Context context;

    public DatabaseAdapter(Context context){
        this.context = context;
    }

    private void openDatabase() throws SQLiteException{
        DatabaseHelper databaseHelper = new DatabaseHelper(context, DB_NAME);
        SQLiteDatabase db = null;
        if(!checkDatabase()){
            try{
                //Tried to create db before copying, so file should exist
                db = databaseHelper.getReadableDatabase();
                db.close();

                copyDatabase();

            }catch(IOException exception){
                Log.d("DatabaseAdapter", "Error copying DB: "+exception);
            }
        }

        database = SQLiteDatabase.openDatabase(DB_PATH+DB_NAME, null, SQLiteDatabase.OPEN_READONLY);
    }

    private void closeDatabase(){
        database.close();
    }

    public ArrayList<String> queryCategories(){
        try{
            openDatabase();
        }catch(SQLiteException exc){
            exc.printStackTrace();
        }
        //.............................
        return result;
    }

    private boolean checkDatabase(){
        File dbFile = new File(DB_PATH + DB_NAME);
        return dbFile.exists();
    }

    private void copyDatabase() throws IOException{
        InputStream inputStream = context.getAssets().open(DB_NAME);

        String outFileName = DB_PATH + DB_NAME;

        OutputStream outputStream = new FileOutputStream(outFileName);

        byte[] buffer = new byte[1024];
        int length;
        while ((length = inputStream.read(buffer))>0){
            outputStream.write(buffer, 0, length);
        }

        outputStream.flush();
        outputStream.close();
        inputStream.close();
    }

}

DatabaseHelper很简单:

ublic class DatabaseHelper extends SQLiteOpenHelper {

    public DatabaseHelper(Context context, String name){
        super(context, name, null, 1);

    }


    @Override
    public void onCreate(SQLiteDatabase arg0) {
        // TODO Auto-generated method stub

    }

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

    }

}

尝试了一切!我试着玩延伸!但我仍然得到一个错误: 复制数据库时出错:java.io.FileNotFoundException: /data/data/com.mypackage/databases/database.sqlite (No such file or directory)

我在模拟器上查了一下,我的文件就在那里,所以我应该可以写了! 请帮忙!这让我疯了!

UPD 我试图把它放在SD卡上然后就可以了。但仍然无法理解为什么我无法将其写入app数据文件夹。

4 个答案:

答案 0 :(得分:7)

我使用这个助手并且工作正常:

public class DBHelper extends SQLiteOpenHelper{

private final static String DB_PATH = "/data/data/[YOUR PACKAGE HERE]/databases/";

String dbName;
Context context;

File dbFile;

public DBHelper(Context context, String dbName, CursorFactory factory,
        int version) {
    super(context, dbName, factory, version);
    this.context = context;
    this.dbName = dbName;
    dbFile= new File(DB_PATH + dbName);
}

@Override
public synchronized SQLiteDatabase getWritableDatabase() {

    if(!dbFile.exists()){
        SQLiteDatabase db = super.getWritableDatabase();
        copyDataBase(db.getPath());
    }
    return super.getWritableDatabase();
}

@Override
public synchronized SQLiteDatabase getReadableDatabase() {
    if(!dbFile.exists()){
        SQLiteDatabase db = super.getReadableDatabase();
        copyDataBase(db.getPath());
    }
    return super.getReadableDatabase();
}

@Override
public void onCreate(SQLiteDatabase db) {}

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

private void copyDataBase(String dbPath){
    try{
        InputStream assestDB = context.getAssets().open("databases/"+dbName);

        OutputStream appDB = new FileOutputStream(dbPath,false);

        byte[] buffer = new byte[1024];
        int length;
        while ((length = assestDB.read(buffer)) > 0) {
            appDB.write(buffer, 0, length);
        }

        appDB.flush();
        appDB.close();
        assestDB.close();
    }catch(IOException e){
        e.printStackTrace();
    }

}

}

考虑到数据库的文件扩展名是 .db ,并且我的数据库是 assets / databases /

答案 1 :(得分:3)

我有同样的问题,我用另一种方法修复了它。 一开始,我按照每个人的说法声明了数据库路径:

dbPath="data/data/<my package name>/databases/data.db"

这是一个确切的路径,没有错。但是当我尝试打开OutPutFileStream来复制数据库时,它总是会失败。我不知道为什么。然后,我改变了打开数据库的方式,如下所示:

dbPath = context.getDatabasePath(dbName);
OutputStream myOutput = new FileOutputStream(dbPath.getAbsolutePath());

这个问题已经解决了。太惊讶了。

希望这有帮助。

答案 2 :(得分:2)

public static void copyDatabase(final Context ctx, String dbName) {
    if (ctx != null) {
        File f = ctx.getDatabasePath(dbName);
        if (!f.exists()) {

            // check databases exists
            if (!f.getParentFile().exists())
                f.getParentFile().mkdir();

            try {
                InputStream in = ctx.getAssets().open(dbName);
                OutputStream out = new FileOutputStream(f.getAbsolutePath());

                byte[] buffer = new byte[1024];
                int length;
                while ((length = in.read(buffer)) > 0) {
                    out.write(buffer, 0, length);
                }
                in.close();
                out.close();
                Logger.i("Database copy successed! " + f.getPath());
            } catch (Exception ex) {
                Logger.e(ex);
            }
        }
    }
}

答案 3 :(得分:1)

请检查OutputStream之前的数据库文件夹。

像这样,

File databaseFile = new File(context.getFilesDir().getAbsolutePath()
            .replace("files", "databases"));

// check if databases folder exists, if not create it.
if (!databaseFile.exists()){
    databaseFile.mkdir();
}