【问题标题】:copying sqlite db to android device fails将 sqlite db 复制到 android 设备失败
【发布时间】:2011-07-23 13:43:24
【问题描述】:

我有一个复制到“资产”文件夹的 sqlite 数据库。在我的程序中,我检查数据库是否已经存在,如果不存在,我创建一个新的并复制它。 我使用(或多或少)来自http://www.reigndesign.com/blog/using-your-own-sqlite-database-in-android-applications/comment-page-2/的代码

    public void createDataBase() throws IOException {
    boolean dbExist = checkDataBase();

    if (dbExist) {
        Log.i(DEBUG_TAG, "createDataBase -> Datenbank existiert");
        // do nothing - database already exist
    } else {
        // By calling this method and empty database will be created into
        // the default system path
        // of your application so we are gonna be able to overwrite that
        // database with our database.
        this.getReadableDatabase();
        Log.i(DEBUG_TAG, "else, db existiert nicht 1");
        try {
            copyDataBase();
            Log.i(DEBUG_TAG, "nach copydatabase");
        } catch (IOException e) {
            throw new Error("Error copying database");
        }
    }
}

/**
 * Checked ob Database bereits existiert
 * 
 * @return
 */
private boolean checkDataBase() throws SQLiteException {
    SQLiteDatabase checkDB = null;
    Boolean checkTable = false;
    try {
        String myPath = DB_PATH + DB_NAME;
        checkDB = SQLiteDatabase.openDatabase(myPath, null,
                SQLiteDatabase.OPEN_READWRITE);
        Log.i(DEBUG_TAG, "checkdatabase1");

    } catch (SQLiteException e) {
        Log.e(DEBUG_TAG, "Fehler checkDataBase: ", e);
    }
    if (checkDB != null) {
        checkDB.close();
    }
    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 transfering bytestream.
 * */
private void copyDataBase() throws IOException {
    // Open your local db as the input stream
    InputStream myInput = dbContext.getAssets().open(DB_NAME);

    // Path to the just created empty db
    String outFileName = DB_PATH + 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];
    int length;
    while ((length = myInput.read(buffer)) > 0) {
        myOutput.write(buffer, 0, length);
    }

    // Close the streams
    myOutput.flush();
    myOutput.close();
    myInput.close();
    Log.i(DEBUG_TAG, "copydatabase");
}

在模拟器中它工作得非常好。

然后我尝试在我的设备 (HTC Desire HD) 上运行它。我收到以下消息:

03-26 17:02:05.053: INFO/Database(24458): sqlite returned: error code = 14, msg = cannot open file at line 27206 of [42537b6056]

当我第一次尝试打开数据库时会发生这种情况。当我在模拟器中运行程序时,我没有收到此消息。当我第二次运行程序时,它找到了数据库,打开没有错误,但表不存在。

我已经在模拟器和设备上调试了几次程序,但没有找到任何解决方案。

这可能是某种权限问题吗? (因为我也无法通过 adb --> 权限被拒绝'看到设备上的数据库)

我对 android 很陌生,所以也许我错过了一些愚蠢的东西......

谢谢

【问题讨论】:

    标签: android sqlite device htc-android


    【解决方案1】:

    我通过创建自己的目录并将文件放在目录中来使其工作

    String path=mContext.getDir("Folder_name", Context.MODE_WORLD_WRITEABLE).getAbsolutePath();
    

    创建文件夹的代码。

    然后进行我们的检查数据库和复制数据库的操作。

    enter code here 
    
     public void createDataBase() throws IOException { 
     String path=mContext.getDir("Folder_Name", Context.MODE_WORLD_WRITEABLE).getAbsolutePath();
     DB_PATH=path;
     boolean mDataBaseExist = checkDataBase(); 
     if(!mDataBaseExist) 
     { 
       try  
        { 
         copyDataBase(); 
        }  
        catch (IOException mIOException)  
        { 
        Log.d("Exception",mIOException.getMessage());
        throw new Error("ErrorCopyingDataBase"); 
        } 
    } 
    }
    
    
    private boolean checkDataBase() 
    { 
        Log.d(TAG, "In checkDataBase :::::"); 
        File dbFile = new File( DB_PATH+DATABASE_NAME); 
        Log.d("dbFile", dbFile + "   "+ dbFile.exists()); 
        return dbFile.exists(); 
    } 
    
    //Copy the database from assets 
    private void copyDataBase() throws IOException 
    { 
        Log.d(TAG, "In copyDataBase :::::"); 
        InputStream mInput = mContext.getAssets().open(DB_NAME);
        String outFileName = DB_PATH  + DATABASE_NAME;
    
        Log.d(TAG, "In copyDataBase  outFileName:::::"+outFileName);
    
        OutputStream mOutput = new FileOutputStream(outFileName); 
        byte[] mBuffer = new byte[1024]; 
        int mLength; 
        while ((mLength = mInput.read(mBuffer))>0) 
        { 
            mOutput.write(mBuffer, 0, mLength); 
        } 
        mOutput.flush(); 
        mOutput.close(); 
        mInput.close(); 
    } 
    
    //Open the database, so we can query it 
    public boolean openDataBase() throws SQLException 
    { 
        //DB_PATH +
        String mPath = DB_PATH+ DATABASE_NAME; 
        Log.v("mPath", mPath); 
        mDataBase = SQLiteDatabase.openDatabase(mPath, null, SQLiteDatabase.CREATE_IF_NECESSARY); 
        return mDataBase != null; 
    } 
    

    希望对新人有所帮助。

    干杯

    【讨论】:

      【解决方案2】:
      1. 不要通过字符串连接创建路径。使用适当的File 构造函数。
      2. 您的DB_PATH 可能无效,但由于您拒绝显示,我们无法确定。
      3. 如果此代码来自的类是SQLiteOpenHelper,则您对getReadableDatabase() 的调用将创建一个空数据库。
      4. “(因为我也无法通过 adb 看到设备上的数据库 --> 权限被拒绝'” - 这是预期的,因为您无权在生产设备上查看该目录。

      【讨论】:

      • 感谢您的回答。 File 构造函数的提示非常有用。我在anddev.org/networking-database-problems-f29/… 上找到了解决方案,我不知道这是一个特定于设备的问题,所以我用谷歌搜索了几个小时的错误关键词。
      • @user678199 :非常感谢您的链接... :) 这应该是一个答案...不是评论..
      猜你喜欢
      • 2014-05-29
      • 2016-05-23
      • 1970-01-01
      • 2015-08-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-08-26
      相关资源
      最近更新 更多