获得"无法打开数据库"错误抄袭资产SQLite数据库时,在安卓4.2 [英] Getting "Failed to open database" error when copying a sqlite database from assets In Android 4.2
本文介绍了获得"无法打开数据库"错误抄袭资产SQLite数据库时,在安卓4.2的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!
问题描述
我的code正常工作为Android 2.3,但我不知道为什么它不针对Android 4.2的工作
我的异常日志是这里
9月一日至17日:54:04.411:E / SQLiteLog(24202):(14)无法打开文件在30176行[00bb9c9ce4]
9月1号至17日:54:04.411:E / SQLiteLog(24202):(14)os_unix.c:30176:(2)开(/data/data/com.example.myapp/databases/myapp.db) -
无法打开数据库/data/data/com.example.mypapp/databases/myapp.db。
android.database.sqlite.SQLiteCantOpenDatabaseException:未知错误(code 14):无法打开数据库
在android.database.sqlite.SQLiteConnection.nativeOpen(本机方法)
在android.database.sqlite.SQLiteConnection.open(SQLiteConnection.java:209)
在android.database.sqlite.SQLiteConnection.open(SQLiteConnection.java:193)
在android.database.sqlite.SQLiteConnectionPool.openConnectionLocked(SQLiteConnectionPool.java:463)
在android.database.sqlite.SQLiteConnectionPool.open(SQLiteConnectionPool.java:185)
在android.database.sqlite.SQLiteConnectionPool.open(SQLiteConnectionPool.java:177)
在android.database.sqlite.SQLiteDatabase.openInner(SQLiteDatabase.java:804)
在android.database.sqlite.SQLiteDatabase.open(SQLiteDatabase.java:789)
在android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:694)
在android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:669)
在com.example.myapp.DataBaseHelper.checkDataBase(DataBaseHelper.java:80)
在com.example.myapp.DataBaseHelper.createDataBase(DataBaseHelper.java:47)
在com.example.myapp.MainActivity.onCreate(MainActivity.java:61)
在android.app.Activity.performCreate(Activity.java:5104)
在android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1080)
在android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2144)
在android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2230)
在android.app.ActivityThread.access $ 600(ActivityThread.java:141)
在android.app.ActivityThread $ H.handleMessage(ActivityThread.java:1234)
在android.os.Handler.dispatchMessage(Handler.java:99)
在android.os.Looper.loop(Looper.java:137)
在android.app.ActivityThread.main(ActivityThread.java:5039)
在java.lang.reflect.Method.invokeNative(本机方法)
在java.lang.reflect.Method.invoke(Method.java:511)
在com.android.internal.os.ZygoteInit $ MethodAndArgsCaller.run(ZygoteInit.java:793)
在com.android.internal.os.ZygoteInit.main(ZygoteInit.java:560)
在dalvik.system.NativeStart.main(本机方法)
我的 MainActivity.java
公共类MainActivity延伸活动{
公共无效的onCreate(包冰柱){
super.onCreate(冰柱);
的setContentView(R.layout.activity_main);
DataBaseHelper myDbHelper;
myDbHelper =新DataBaseHelper(本);
尝试 {
myDbHelper.createDataBase();
}赶上(IOException异常IOE){
抛出新的错误(无法创建数据库);
}
尝试 {
myDbHelper.openDataBase();
}赶上(的SQLException SQLE){
扔SQLE;
} 最后 {
myDbHelper.close();
}
}}
我的 DatabaseHelper.java
公共类DataBaseHelper扩展SQLiteOpenHelper {
//而Android的默认系统应用程序的数据库路径。
私有静态字符串DB_PATH =/data/data/com.example.myapp/databases/;
私有静态字符串DB_NAME =myapp.db;
私人SQLiteDatabase MyDatabase的;
私人最终语境myContext;
/ **
*构造函数
*注意到并保持传递的上下文中的一个参考,以便访问该应用程序的资产和资源。
* @参数方面
* /
公共DataBaseHelper(上下文的背景下){
超级(上下文,DB_NAME,空,1);
this.myContext =背景;
}
/ **
*在系统上创建一个空数据库,并与自己的数据库重写它。
* * /
公共无效的CreateDatabase()抛出IOException异常{
布尔dbExist = checkDataBase();
如果(dbExist){
//什么也不做 - 数据库中已存在
}其他{
//通过调用这个方法和空的数据库将被创建到系统默认路径
//你的应用程序,所以我们要能够覆盖数据库,我们的数据库。
this.getReadableDatabase();
尝试 {
copyDataBase();
}赶上(IOException异常E){
抛出新的错误(错误复制数据库);
}
}
}
/ **
*检查数据库中已存在,以避免重新复制每次打开应用程序时,该文件。
* @返回true,如果它存在,虚假的,如果它不
* /
私人布尔checkDataBase(){
SQLiteDatabase CHECKDB = NULL;
尝试{
字符串mypath中= DB_PATH + DB_NAME;
CHECKDB = SQLiteDatabase.openDatabase(mypath中,空,SQLiteDatabase.OPEN_READONLY);
}赶上(SQLiteException E){
Log.i(Hellloooo,e.getMessage());
//数据库的简化版,存在。
}
如果(CHECKDB!= NULL){
checkDB.close();
}
返回CHECKDB!= NULL?真假;
}
/ **
*复制你的数据库从当地的资产文件夹在刚才创建的空数据库
*系统文件夹,从那里它可以被访问和处理。
*这是通过transfering字节流进行。
* * /
私人无效copyDataBase()抛出IOException异常{
//打开本地数据库作为输入流
InputStream的myInput = myContext.getAssets()开(DB_NAME)。
//路径刚刚创建的空分贝
字符串outFileName = DB_PATH + DB_NAME;
//打开空分贝的输出流
的OutputStream myOutput =新的FileOutputStream(outFileName);
//传输的字节从inputfile中的OUTPUTFILE
byte []的缓冲区=新的字节[1024];
INT长;
而((长度= myInput.read(缓冲液))大于0){
myOutput.write(缓冲液,0,长度);
}
//关闭流
myOutput.flush();
myOutput.close();
myInput.close();
}
公共无效的openDatabase()抛出的SQLException {
//打开数据库
字符串mypath中= DB_PATH + DB_NAME;
MyDatabase的= SQLiteDatabase.openDatabase(mypath中,空,SQLiteDatabase.OPEN_READONLY);
}
@覆盖
市民同步无效的close(){
如果(MyDatabase的!= NULL)
myDataBase.close();
super.close();
}
@覆盖
公共无效的onCreate(SQLiteDatabase DB){
}
@覆盖
公共无效onUpgrade(SQLiteDatabase分贝,INT oldVersion,诠释静态网页){
}
//添加您的公共辅助方法来访问,并从数据库中获取的内容。
//你可以做返回游标返回myDataBase.query(....),因此这将会是很容易
//你来创造适配器的意见。
}
解决方案
我不得不修改 checkDataBase()到
私人布尔checkDataBase(){
布尔CHECKDB = FALSE;
尝试{
字符串mypath中= myContext.getFilesDir()getAbsolutePath()代替(文件,数据库)+文件分割符+ DB_NAME。;
文件DBFILE =新的文件(mypath中);
CHECKDB = dbfile.exists();
}
赶上(SQLiteException E){
的System.out.println(数据库不存在);
}
返回CHECKDB;
}
My Code works fine For Android 2.3 but i don't know why it doesn't work for Android 4.2
My Exception log is here
01-17 09:54:04.411: E/SQLiteLog(24202): (14) cannot open file at line 30176 of [00bb9c9ce4]
01-17 09:54:04.411: E/SQLiteLog(24202): (14) os_unix.c:30176: (2) open(/data/data/com.example.myapp/databases/myapp.db) -
Failed to open database '/data/data/com.example.mypapp/databases/myapp.db'.
android.database.sqlite.SQLiteCantOpenDatabaseException: unknown error (code 14): Could not open database
at android.database.sqlite.SQLiteConnection.nativeOpen(Native Method)
at android.database.sqlite.SQLiteConnection.open(SQLiteConnection.java:209)
at android.database.sqlite.SQLiteConnection.open(SQLiteConnection.java:193)
at android.database.sqlite.SQLiteConnectionPool.openConnectionLocked(SQLiteConnectionPool.java:463)
at android.database.sqlite.SQLiteConnectionPool.open(SQLiteConnectionPool.java:185)
at android.database.sqlite.SQLiteConnectionPool.open(SQLiteConnectionPool.java:177)
at android.database.sqlite.SQLiteDatabase.openInner(SQLiteDatabase.java:804)
at android.database.sqlite.SQLiteDatabase.open(SQLiteDatabase.java:789)
at android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:694)
at android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:669)
at com.example.myapp.DataBaseHelper.checkDataBase(DataBaseHelper.java:80)
at com.example.myapp.DataBaseHelper.createDataBase(DataBaseHelper.java:47)
at com.example.myapp.MainActivity.onCreate(MainActivity.java:61)
at android.app.Activity.performCreate(Activity.java:5104)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1080)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2144)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2230)
at android.app.ActivityThread.access$600(ActivityThread.java:141)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1234)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:5039)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:793)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:560)
at dalvik.system.NativeStart.main(Native Method)
My MainActivity.java
public class MainActivity extends Activity {
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
setContentView(R.layout.activity_main);
DataBaseHelper myDbHelper;
myDbHelper = new DataBaseHelper(this);
try {
myDbHelper.createDataBase();
} catch (IOException ioe) {
throw new Error("Unable to create database");
}
try {
myDbHelper.openDataBase();
} catch (SQLException sqle) {
throw sqle;
} finally {
myDbHelper.close();
}
}}
My DatabaseHelper.java
public class DataBaseHelper extends SQLiteOpenHelper{
//The Android's default system path of your application database.
private static String DB_PATH = "/data/data/com.example.myapp/databases/";
private static String DB_NAME = "myapp.db";
private SQLiteDatabase myDataBase;
private final Context myContext;
/**
* Constructor
* Takes and keeps a reference of the passed context in order to access to the application assets and resources.
* @param context
*/
public DataBaseHelper(Context context) {
super(context, DB_NAME, null, 1);
this.myContext = context;
}
/**
* Creates a empty database on the system and rewrites it with your own database.
* */
public void createDataBase() throws IOException{
boolean dbExist = checkDataBase();
if(dbExist){
//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();
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){
Log.i("Hellloooo", e.getMessage());
//database does't exist yet.
}
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 = myContext.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();
}
public void openDataBase() throws SQLException{
//Open the database
String myPath = DB_PATH + DB_NAME;
myDataBase = SQLiteDatabase.openDatabase(myPath, null, SQLiteDatabase.OPEN_READONLY);
}
@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) {
}
// Add your public helper methods to access and get content from the database.
// You could return cursors by doing "return myDataBase.query(....)" so it'd be easy
// to you to create adapters for your views.
}
解决方案
I had to modify checkDataBase() to
private boolean checkDataBase(){
boolean checkdb = false;
try{
String myPath = myContext.getFilesDir().getAbsolutePath().replace("files", "databases")+File.separator + DB_NAME;
File dbfile = new File(myPath);
checkdb = dbfile.exists();
}
catch(SQLiteException e){
System.out.println("Database doesn't exist");
}
return checkdb;
}
这篇关于获得"无法打开数据库"错误抄袭资产SQLite数据库时,在安卓4.2的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!
查看全文