复制SQLite数据库到Android设备失败

4
我有一个sqlite数据库,我将其复制到“asset”文件夹中。在我的程序中,我检查数据库是否已经存在,如果不存在,则创建一个新的并复制它。 我使用了(或多或少)来自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非常新,所以可能只是忽略了一些愚蠢的事情...
谢谢
2个回答

0

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

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; 
} 

希望这能帮助新手们。
祝好。

0
  1. 不要通过字符串拼接创建路径。使用适当的File构造函数。
  2. 你的DB_PATH可能无效,但由于你拒绝展示它,我们不能确定。
  3. 如果这段代码所在的类是一个SQLiteOpenHelper,那么调用getReadableDatabase()将会创建一个空数据库。
  4. "(因为我也无法通过adb在设备上看到数据库-->权限被拒绝")-- 这是正常的,因为你没有权限在生产设备上查看该目录。

1
感谢您的回答。使用File构造函数的提示非常有用。我在http://www.anddev.org/networking-database-problems-f29/missing-table-in-sqlite-with-specific-version-of-desire-hd-t50364.html上找到了解决方案。我不知道这是一个设备特定的问题,所以我花了几个小时用错误的关键词进行谷歌搜索。 - user678199
@user678199:非常感谢提供链接... :) 这应该是一个答案,而不是评论.. - Deepzz

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接