【问题标题】:Can't copy SQLite database from assets无法从资产中复制 SQLite 数据库
【发布时间】:2011-11-08 14:50:08
【问题描述】:

我尝试从 assets 目录中复制 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 卡上,它可以工作。但还是不明白为什么我不能将它写入应用数据文件夹。

【问题讨论】:

    标签: java android sqlite


    【解决方案1】:

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

    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/

    【讨论】:

    • 如何在复制的数据库中添加记录?
    【解决方案2】:

    我有同样的问题,我已经用另一种方法解决了它。 一开始我和大家一样声明了数据库路径:

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

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

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

    问题已解决。太惊喜了。

    希望这会有所帮助。

    【讨论】:

      【解决方案3】:
      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);
                  }
              }
          }
      }
      

      【讨论】:

      • 你应该添加一些 cmets。
      【解决方案4】:

      请检查您的 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();
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多