1

我已将我的 sqlite 数据库文件放在“assets”文件夹中,并且我编写了一个 DataManager 类来从数据库中获取数据,但是我遇到了运行时CreateDataBase()错误。请帮我解决问题

这是我的 Datamanager 类。我正在为 android 预创建数据库,但我正在获取文件未找到异常,请帮助我..我在下面显示了我的 Logcat。

(数据管理器类)

package com.example.applicationdatabase;
import android.content.ContentValues;
import android.database.Cursor;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteException;
import android.database.sqlite.SQLiteOpenHelper;

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;


public class DataBaseManager extends SQLiteOpenHelper {

    // The Android's default system path of your application database.
    //data/data/ and /databases remain the same always. The one that must be changed is com.example which represents
    //the MAIN package of your project
    private static String DB_PATH = "/data/data/com.example.applicationdatabase/databases";

    //the name of your database
    private static String DB_NAME = "database";

    private static SQLiteDatabase mDataBase;

    private static DataBaseManager sInstance = null;
    // database version    
    private static final int DATABASE_VERSION = 1;

    /**
     * Constructor Takes and keeps a reference of the passed context in order to
     * access to the application assets and resources.
     */
    private DataBaseManager() {
        super(ApplicationContextProvider.getContext(), DB_NAME, null, DATABASE_VERSION);

        try {
            createDataBase();
            openDataBase();
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

    /**
     * Singleton for DataBase
     *
     * @return singleton instance
     */
    public static DataBaseManager instance() {

        if (sInstance == null) {
            sInstance = new DataBaseManager();
        }
        return sInstance;
    }


    /**
     * Creates a empty database on the system and rewrites it with your own
     * database.
     *
     * @throws java.io.IOException io exception
     */
    private void createDataBase() throws IOException {

        boolean dbExist = checkDataBase();

        if (dbExist) {
            // do nothing - database already exist
        } else {

            // By calling this method an 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();

            try {    copyDataBase();

            } catch (IOException e) {

                throw new Error("Error copying database");
            }
        }
    }

    /**
     * Check if the database already exist to avoid re-copying the file each
     * time you open the application.
     *
     * @return true if it exists, false if it doesn't
     */
    private boolean checkDataBase() {

        SQLiteDatabase checkDB = null;

        try {
            String myPath = DB_PATH + DB_NAME;
            checkDB = SQLiteDatabase.openDatabase(myPath, null, SQLiteDatabase.OPEN_READONLY);

        } catch (SQLiteException e) {

            // database doesn't exist yet.

        }

        if (checkDB != null) {

            checkDB.close();

        }

        return checkDB != null;
    }

    /**
     * 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.
     *
     * @throws java.io.IOException io exception
     */
    public void copyDataBase() throws IOException {

        // Open your local db as the input stream
        InputStream myInput =ApplicationContextProvider.getContext().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();

    }

    private void openDataBase() throws SQLException {

        // Open the database
        String myPath = DB_PATH + DB_NAME;
        mDataBase = SQLiteDatabase.openDatabase(myPath, null,
                SQLiteDatabase.OPEN_READWRITE);
    }

    /**
     * Select method
     *
     * @param query select query
     * @return - Cursor with the results
     * @throws android.database.SQLException sql exception
     */
    public Cursor select(String query) throws SQLException {
        return mDataBase.rawQuery(query, null);
    }

    /**
     * Insert method
     *
     * @param table  - name of the table
     * @param values values to insert
     * @throws android.database.SQLException sql exception
     */
    public void insert(String table, ContentValues values) throws SQLException {
        mDataBase.insert(table, null, values);
    }

    /**
     * Delete method
     *
     * @param table - table name
     * @param where WHERE clause, if pass null, all the rows will be deleted
     * @throws android.database.SQLException sql exception
     */
    public void delete(String table, String where) throws SQLException {

        mDataBase.delete(table, where, null);

    }

    /**
     * Update method
     *
     * @param table  - table name
     * @param values - values to update
     * @param where  - WHERE clause, if pass null, all rows will be updated
     */
    public void update(String table, ContentValues values, String where) {

        mDataBase.update(table, values, where, null);

    }

    /**
     * Let you make a raw query
     *
     * @param command - the sql comand you want to run
     */
    public void sqlCommand(String command) {
        mDataBase.execSQL(command);
    }

    @Override
    public synchronized void close() {

        if (mDataBase != null)
            mDataBase.close();

        super.close();

    }

    @Override
    public void onCreate(SQLiteDatabase db) {

    }

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

    }

}

日志猫:

11-30 16:02:18.908: E/SQLiteLog(968): (14) cannot open file at line 30176 of [00bb9c9ce4]
11-30 16:02:18.938: E/SQLiteLog(968): (14) os_unix.c:30176: (2) open(/data/data/com.example.applicationdatabase/databasesdatabase) - 
11-30 16:02:18.948: E/SQLiteDatabase(968): Failed to open database '/data/data/com.example.applicationdatabase/databasesdatabase'.
11-30 16:02:18.948: E/SQLiteDatabase(968): android.database.sqlite.SQLiteCantOpenDatabaseException: unknown error (code 14): Could not open database
11-30 16:02:18.948: E/SQLiteDatabase(968):  at android.database.sqlite.SQLiteConnection.nativeOpen(Native Method)
11-30 16:02:18.948: E/SQLiteDatabase(968):  at android.database.sqlite.SQLiteConnection.open(SQLiteConnection.java:209)
11-30 16:02:18.948: E/SQLiteDatabase(968):  at android.database.sqlite.SQLiteConnection.open(SQLiteConnection.java:193)
11-30 16:02:18.948: E/SQLiteDatabase(968):  at android.database.sqlite.SQLiteConnectionPool.openConnectionLocked(SQLiteConnectionPool.java:463)
11-30 16:02:18.948: E/SQLiteDatabase(968):  at android.database.sqlite.SQLiteConnectionPool.open(SQLiteConnectionPool.java:185)
11-30 16:02:18.948: E/SQLiteDatabase(968):  at android.database.sqlite.SQLiteConnectionPool.open(SQLiteConnectionPool.java:177)
11-30 16:02:18.948: E/SQLiteDatabase(968):  at android.database.sqlite.SQLiteDatabase.openInner(SQLiteDatabase.java:804)
11-30 16:02:18.948: E/SQLiteDatabase(968):  at android.database.sqlite.SQLiteDatabase.open(SQLiteDatabase.java:789)
11-30 16:02:18.948: E/SQLiteDatabase(968):  at android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:694)
11-30 16:02:18.948: E/SQLiteDatabase(968):  at android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:669)
11-30 16:02:18.948: E/SQLiteDatabase(968):  at com.example.applicationdatabase.DataBaseManager.checkDataBase(DataBaseManager.java:102)
11-30 16:02:18.948: E/SQLiteDatabase(968):  at com.example.applicationdatabase.DataBaseManager.createDataBase(DataBaseManager.java:69)
11-30 16:02:18.948: E/SQLiteDatabase(968):  at com.example.applicationdatabase.DataBaseManager.<init>(DataBaseManager.java:39)
11-30 16:02:18.948: E/SQLiteDatabase(968):  at com.example.applicationdatabase.DataBaseManager.instance(DataBaseManager.java:55)
11-30 16:02:18.948: E/SQLiteDatabase(968):  at com.example.applicationdatabase.DBActivity.onCreate(DBActivity.java:35)
11-30 16:02:18.948: E/SQLiteDatabase(968):  at android.app.Activity.performCreate(Activity.java:5104)
11-30 16:02:18.948: E/SQLiteDatabase(968):  at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1080)
11-30 16:02:18.948: E/SQLiteDatabase(968):  at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2144)
11-30 16:02:18.948: E/SQLiteDatabase(968):  at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2230)
11-30 16:02:18.948: E/SQLiteDatabase(968):  at android.app.ActivityThread.access$600(ActivityThread.java:141)
11-30 16:02:18.948: E/SQLiteDatabase(968):  at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1234)
11-30 16:02:18.948: E/SQLiteDatabase(968):  at android.os.Handler.dispatchMessage(Handler.java:99)
11-30 16:02:18.948: E/SQLiteDatabase(968):  at android.os.Looper.loop(Looper.java:137)
11-30 16:02:18.948: E/SQLiteDatabase(968):  at android.app.ActivityThread.main(ActivityThread.java:5039)
11-30 16:02:18.948: E/SQLiteDatabase(968):  at java.lang.reflect.Method.invokeNative(Native Method)
11-30 16:02:18.948: E/SQLiteDatabase(968):  at java.lang.reflect.Method.invoke(Method.java:511)
11-30 16:02:18.948: E/SQLiteDatabase(968):  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:793)
11-30 16:02:18.948: E/SQLiteDatabase(968):  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:560)
11-30 16:02:18.948: E/SQLiteDatabase(968):  at dalvik.system.NativeStart.main(Native Method)
11-30 16:02:19.008: E/AndroidRuntime(968): FATAL EXCEPTION: main
11-30 16:02:19.008: E/AndroidRuntime(968): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.applicationdatabase/com.example.applicationdatabase.DBActivity}: java.lang.NullPointerException
11-30 16:02:19.008: E/AndroidRuntime(968):  at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2180)
11-30 16:02:19.008: E/AndroidRuntime(968):  at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2230)
11-30 16:02:19.008: E/AndroidRuntime(968):  at android.app.ActivityThread.access$600(ActivityThread.java:141)
11-30 16:02:19.008: E/AndroidRuntime(968):  at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1234)
11-30 16:02:19.008: E/AndroidRuntime(968):  at android.os.Handler.dispatchMessage(Handler.java:99)
11-30 16:02:19.008: E/AndroidRuntime(968):  at android.os.Looper.loop(Looper.java:137)
11-30 16:02:19.008: E/AndroidRuntime(968):  at android.app.ActivityThread.main(ActivityThread.java:5039)
11-30 16:02:19.008: E/AndroidRuntime(968):  at java.lang.reflect.Method.invokeNative(Native Method)
11-30 16:02:19.008: E/AndroidRuntime(968):  at java.lang.reflect.Method.invoke(Method.java:511)
11-30 16:02:19.008: E/AndroidRuntime(968):  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:793)
11-30 16:02:19.008: E/AndroidRuntime(968):  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:560)
11-30 16:02:19.008: E/AndroidRuntime(968):  at dalvik.system.NativeStart.main(Native Method)
11-30 16:02:19.008: E/AndroidRuntime(968): Caused by: java.lang.NullPointerException
11-30 16:02:19.008: E/AndroidRuntime(968):  at android.database.sqlite.SQLiteOpenHelper.getDatabaseLocked(SQLiteOpenHelper.java:224)
11-30 16:02:19.008: E/AndroidRuntime(968):  at android.database.sqlite.SQLiteOpenHelper.getReadableDatabase(SQLiteOpenHelper.java:188)
11-30 16:02:19.008: E/AndroidRuntime(968):  at com.example.applicationdatabase.DataBaseManager.createDataBase(DataBaseManager.java:79)
11-30 16:02:19.008: E/AndroidRuntime(968):  at com.example.applicationdatabase.DataBaseManager.<init>(DataBaseManager.java:39)
11-30 16:02:19.008: E/AndroidRuntime(968):  at com.example.applicationdatabase.DataBaseManager.instance(DataBaseManager.java:55)
11-30 16:02:19.008: E/AndroidRuntime(968):  at com.example.applicationdatabase.DBActivity.onCreate(DBActivity.java:35)
11-30 16:02:19.008: E/AndroidRuntime(968):  at android.app.Activity.performCreate(Activity.java:5104)
11-30 16:02:19.008: E/AndroidRuntime(968):  at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1080)
11-30 16:02:19.008: E/AndroidRuntime(968):  at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2144)
11-30 16:02:19.008: E/AndroidRuntime(968):  ... 11 more
4

4 回答 4

2

这是从 Assest 文件夹中读取数据库的工作代码。唯一的问题是它无法找到的 PATH。

我希望它可以帮助某人,如果有任何疑问请给我留言...

package net.learn2develop.Databases;

import java.io.IOException;

import android.app.Activity;

import android.database.Cursor;
import android.database.SQLException;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;

public class DatabasesActivity extends Activity {

    protected static final String TAG = null;
    private Button insertButton;
    private Button updateButton;
    private Button deleteButton;
    private Button displayButton;
    boolean status = false;

    private EditText name;
    private EditText email;
    protected int value1;

    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        DBAdapter myDbHelper = new DBAdapter(null);
        myDbHelper = new DBAdapter(this);

        insertButton = (Button) findViewById(R.id.btnInsert);
        updateButton = (Button) findViewById(R.id.btnUpdate);
        deleteButton = (Button) findViewById(R.id.btnDelete);
        displayButton = (Button) findViewById(R.id.btnDisplay);
        name = (EditText) findViewById(R.id.edit_name);
        email = (EditText) findViewById(R.id.edit_email);

        // --- inserting ------
        insertButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {

                if (name.getText().toString().trim().length() == 0)
                {
                    Toast msg = Toast.makeText(getBaseContext(),
                            "Please Enter Name ", Toast.LENGTH_LONG);
                    msg.show();
                }
                else if (email.getText().toString().trim().length() == 0)
                {
                    Toast msg = Toast.makeText(getBaseContext(),
                            "Please Enter Email", Toast.LENGTH_LONG);
                    msg.show();
                }
                else

                    insertRecord();
            }
        });

        // --------Deleting the Records -----------
        deleteButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                deleteRecord();
            }
        });

        // --- Displaying the Records -------
        displayButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                DisplayRecord();
            }
        });

        updateButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {

                if (name.getText().toString().trim().length() == 0)
                {
                    Toast msg = Toast.makeText(getBaseContext(),
                            "Please Enter Name ", Toast.LENGTH_LONG);
                    msg.show();
                }
                else if (email.getText().toString().trim().length() == 0)
                {
                    Toast msg = Toast.makeText(getBaseContext(),
                            "Please Enter Email", Toast.LENGTH_LONG);
                    msg.show();
                }
                else
                {
                    updateRecord();
                }
            }
        });

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

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

    }

    protected void DisplayRecord() {
        DBAdapter myDbHelper1 = new DBAdapter(null);
        myDbHelper1.openDataBase();
        Cursor c = myDbHelper1.getAllContacts();

        if (c.moveToFirst()) {
            do {
                DisplayContact(c);
            } while (c.moveToNext());
        }
        myDbHelper1.close();
    }

    protected void updateRecord() {

        String Name = fetchName();
        String Email = fetchEmail();

        DBAdapter myDbHelper1 = new DBAdapter(null);
        myDbHelper1.openDataBase();
        if (myDbHelper1.updateContact(1, Name, Email))
        {
            Toast msg = Toast.makeText(getBaseContext(),
                    "Update Successfully ", Toast.LENGTH_LONG);
            msg.show();
        }
        else
        {
            Toast msg = Toast.makeText(getBaseContext(),
                    "Update Failed ", Toast.LENGTH_LONG);
            msg.show();
        }
        myDbHelper1.close();

    }

    protected void deleteRecord() {
        DBAdapter myDbHelper1 = new DBAdapter(null);

        myDbHelper1.openDataBase();
        if (myDbHelper1.deleteContact(27))
        {
            Toast msg = Toast.makeText(getBaseContext(),
                    "Delete Successfully ", Toast.LENGTH_LONG);
            msg.show();
        }
        else
        {
            Toast msg = Toast.makeText(getBaseContext(),
                    "Delete Failed ", Toast.LENGTH_LONG);
            msg.show();
        }
        myDbHelper1.close();

    }

    protected void insertRecord() {
        String Name = fetchName();
        String Email = fetchEmail();

        DBAdapter myDbHelper1 = new DBAdapter(null);
        myDbHelper1.openDataBase();
        long id = myDbHelper1.insertContact(Name, Email);
        myDbHelper1.close();
        Toast msg = Toast.makeText(getBaseContext(),
                "Record: " + id + " Successfully inserted", Toast.LENGTH_LONG);
        msg.show();
        name.setText("");
        email.setText("");

    }

    public void DisplayContact(Cursor c) {
        Toast.makeText(
                this,
                "id: " + c.getString(0) + "\n" + "Name: " + c.getString(1)
                        + "\n" + "Email: " + c.getString(2), Toast.LENGTH_LONG)
                .show();
    }

    public String fetchName()
    {
        String Name = name.getText().trim().toString();
        if (Name.contentEquals(name.getHint()))
        {

            return " ";
        }
        else
        {
            return Name;
        }
    }

    public String fetchEmail()
    {
        String Email = email.getText().trim().toString();
        if (Email.contentEquals(email.getHint()))
        {
            return " ";
        }
        else
        {
            return Email;
        }
    }

}
于 2012-12-01T13:01:12.953 回答
0

我和你遇到了同样的问题,我知道这个错误原因的操作。因为你没有添加写权限,你需要在manifest.xml中添加句-“”

于 2014-05-30T04:00:54.450 回答
0

我认为这个问题来自 HoneyComb,对于早期版本我们没有问题。将代码从 onCreate() 方法移动到 onResume() 方法,并使用 AsyncTasck 进行数据库操作。我希望这能解决问题。或者只需在 DataBaseManager 中编写数据库创建语句(SQL 语句)或将 sql 查询放在任何 xml(原始文件夹内)文件中并处理 xml 文件以创建数据库。

public class DatabaseHelper extends SQLiteOpenHelper {

    public static final String DATABASE_NAME = "mydb.sqlite";

    protected Context context;

    public DatabaseHelper(Context context) {
        super(context, DATABASE_NAME, null, 1);
        this.context = context;
    }

    @Override
    public void onCreate(SQLiteDatabase db) {
        String sqlStatement;
        try {
            InputStream in = context.getResources().openRawResource(R.raw.mydbqueries);
            DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
            Document doc = builder.parse(in, null);
            NodeList statements = doc.getElementsByTagName("statement");
            for (int i=0; i<statements.getLength(); i++) {
                sqlStatement = statements.item(i).getChildNodes().item(0).getNodeValue();
                db.execSQL(sqlStatement);
            }
        } catch (Throwable t) {
        }
    }

    SQLiteDatabase sqliteDB = null;
    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        onCreate(db);
    }

    public SQLiteDatabase open() throws SQLException
    {
        sqliteDB = this.getWritableDatabase();
        return sqliteDB;
    }
}

mydbqueries.xml 内容

<?xml version="1.0" encoding="UTF-8"?><!-- <?xml version="1.0" encoding="utf-8"?> -->
<!-- database queries -->
<sql>
<!-- Meta data table -->
<!-- <statement> CREATE TABLE "android_metadata" ("locale" TEXT DEFAULT 
    'en_US') </statement> Meta data table <statement> INSERT INTO "android_metadata" 
    VALUES('en_US') </statement> -->

<statement>
    sql statement
</statement>
</sql>  
于 2012-11-30T11:34:33.687 回答
0

当您想要访问“/data/data/YOUR-PACKAGE/databases/YOUR-DATABASE”中的数据库但在您访问之前没有任何数据库时会引发此异常。所以你必须创建你的数据库。但是怎么做?在进行任何访问之前,您必须使用以下代码:


SQLiteDatabase db;

db = getWritableDatabase();

if (db != null) {
    b.close();
}
copyDatabase();
于 2014-11-11T08:48:01.170 回答