在Android中打开预先存在的sqlite数据库的问题仍然存在

时间:2012-02-19 22:28:48

标签: android database sqlite listview

新手在这里。我在上一篇文章中收到了一些很好的信息,我希望能得到更多的帮助:)谢谢你的回复。

我正在运送带有应用程序的预先填充的sqlite数据库。我已经完成了通过我在网上找到的例程将数据库从源代码中的assets文件夹复制到/ database /文件夹的过程,我相信你们都熟悉(http://www.reigndesign) .COM /博客/使用 - 你自己的sqlite的数据库功能于Android的应用程序/)。这似乎工作正常。使用DDMS我能够看到数据库被复制并显示在正确的目录中。

然而,现在,我没有得到任何结果。当我检查logcat时,我在尝试打开数据库时看到以下错误:

02-19 14:59:40.490: I/Database(4071): sqlite returned: error code = 14, msg = cannot open file at source line 25467
02-19 14:59:40.490: E/Database(4071): sqlite3_open_v2("/data/data/com.testapp.test/databases/pbaMainDb.sqlite", &handle, 2, NULL) failed

编辑:这是我用于在安装后打开数据库的ListScreen类,并从以下位置执行简单查询:

public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.lists);

   DbHelper db = new DbHelper(this);
    db = new DbHelper(this);



    try {
        db.createDatabase();
    } catch (IOException ioe) {
        throw new Error ("Unable to create database");
    }



    try {
    myDbHelper.close();
    db.openDataBase(); 
    } catch(SQLException sqle){
        throw sqle;
  }




}


public Cursor fetchAllTables() {

    return myDbHelper.rawQuery("SELECT name FROM sqlite_master WHERE type='table'",
            new String[]{});

}

private void fillData() {

    //Cursor c = fetchAllTables();
    //startManagingCursor(c);

    String[] from = new String[] {"name"};
    int[] to = new int[] {R.id.listview};


    SimpleCursorAdapter notes = 
            new SimpleCursorAdapter (this, R.layout.list_view, cursor, from, to);
    setListAdapter(notes);

            }

    }
编辑:另外,从我的DbHelper类(代码是复制我现有的Db),这里是我做的代码(道歉,这是一个转储):

    public class DbHelper extends SQLiteOpenHelper {
// the default android path of the database files it creates
private static String DB_PATH = "/data/data/com.testdata.test/databases/";
private static String DB_NAME = "pbaMainDb.sqlite";
private SQLiteDatabase myDataBase;
private final Context myContext;

// constructor to keep a reference of the passed context in order to access the 

public DbHelper (Context context) {
    super(context, DB_NAME, null, 1);
    this.myContext = context;
}

// Create an empty database and then rewrite with original

public void createDatabase() throws IOException {
    boolean dbExist = CheckDataBase();
    if (dbExist) {
        // if exists, do nothing
    }else {
        //when we call this method the empty database will be created into 
        this.getReadableDatabase();
        try {
                copyDataBase();
        }
        catch (IOException e) {
                throw new Error("Error copying database");
        }
}
    this.close();
}

        // Check if the database already exists to avoid re-copy
private boolean CheckDataBase() {
    SQLiteDatabase checkDB = null;

    try {
        String myPath = DB_PATH + DB_NAME;
        checkDB = SQLiteDatabase.openDatabase(myPath, null                 SQLiteDatabase.OPEN_READWRITE);
        //File dbfile = new File(myPath);
        //return dbfile.exists();
    } catch (SQLiteException e) {
            //database doesn't exist yet
    }
    if (checkDB != null) {
            checkDB.close();
    }
    return checkDB != null ? true : false;
}   
  // Copies database from assets folder to new empty folder

    private void copyDataBase() throws IOException {
        InputStream myInput = myContext.getAssets().open(DB_NAME);

        //path to just created DB

        String outFileName = DB_PATH + DB_NAME;

        OutputStream myOutput = new FileOutputStream (outFileName);

        //transfer bytes from input file to output file

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

        myOutput.flush();
        myOutput.close();
        myInput.close();
    }






    public void openDataBase() throws SQLException {
        // open the database
        String myPath = DB_PATH + DB_NAME;
        myDataBase = SQLiteDatabase.openDatabase(myPath, null, SQLiteDatabase.OPEN_READWRITE);
    }
    @Override
        public synchronized void close() {
            if(myDataBase != null)
                    myDataBase.close();
            super.close();
    }
    @Override
    public void onCreate(SQLiteDatabase db) {
    }

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

}

2 个答案:

答案 0 :(得分:1)

这看似简单,但尝试从数据库名称中取消扩展名。即,当你把它放在你的资产文件夹中时,制作路径"/data/data/com.testapp.test/databases/pbaMainDb"并从文件中取出扩展名。

另外,我认为数据库文件大小可能存在大小限制。你的档案有多大?

最后一种可能性:在应用程序崩溃后,再次打开它(不是编译和安装,只是在设备上再打开它),看看它是否有效。有时第一次创建databases文件夹时,您可能需要进入并使用某些内容创建它

File f = new File(DB_PATH);
if (!f.exists()) {
    f.mkdir();
}

编辑:还有一个问题。查看您使用的教程后,您是否也使用了最后显示的createDataBase()方法?

此外,在执行查询之前,请尝试调用myDbHelper.close();,然后再次调用open方法。他在教程中创建的空版本可能仍处于打开状态,需要在第一时间关闭

让我知道这些如何发展,如果有必要,我会尽力帮助你。

编辑:将我的onCreatefetchAllTables替换为以下编辑内容。出于某种原因,您创建了DbHelper类的两个实例,因此我删除了它。此外,我无法看到您在onCreate上使用的myDbHelper声明的位置,但是除去了对它的所有引用。我们将只使用一个DbHelper实例与数据库进行交互,即db。正如您所看到的,我将其创建为一个类变量,我们将在整个类中使用它,并在onCreate中实例化并打开一次。如果错误发生变化也要注意,因为我现在只关注数据库的开放工作。

DbHelper db;

public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.lists);

    db = new DbHelper(this);

    try {
        db.createDatabase();
    }
    catch (IOException ioe) {
        throw new Error ("Unable to create database");
    }

    try {
        db.close();
        db.openDataBase(); 
    } catch(SQLException sqle){
        throw sqle;
    }
}

public Cursor fetchAllTables() {
    return db.rawQuery("SELECT name FROM sqlite_master WHERE type='table'", null);
}

答案 1 :(得分:0)

我遇到了同样的问题,但作为其中一条评论" http://www.reigndesign.com/blog/using-your-own-sqlite-database-in-android-applications"说,我刚刚这样做了:

替换此行

String myPath = DB_PATH + DB_NAME;

checkDataBase()方法中:

String myPath = Environment.getExternalStorageDirectory() + "/" + DB_NAME;

对我来说效果很好。