1

我嘗試了很多方法將我的sqlite數據庫文件複製到我的/ data/data/packagename/databases文件夾,但我仍然遇到由FileOutputStream對象觸發的FileNotFoundException。 .. 下面的代碼:將資產數據庫從資產複製到設備數據文件夾時出現FileNotFoundException

public static boolean checkCopyDb(Context c, DbHandler _db) { 
    try { 
     String destPath = "/data/data/" + c.getPackageName() + "/databases/db_sociallibraries.db"; 

     File dbFile = new File(destPath); 

     if(!dbFile.exists()) { 
      _db.copyDb(c.getAssets().open(DB_NAME), new FileOutputStream(destPath)); // Line 44 - Throws the exception 
     } 
     return true; 
    } 
    catch (IOException e) { 
     e.printStackTrace(); 
     return false; 
    } 
} 

private void copyDb(InputStream inputStream, OutputStream outputStream) throws IOException { 

    byte[] buffer = new byte[1024]; 
    int length; 

    while((length = inputStream.read(buffer)) > 0) { 
     outputStream.write(buffer,0,length); 
    } 

    inputStream.close(); 
    outputStream.close(); 
} 

這是錯誤:

02-09 01:28:46.384 24222-24222/com.test.michelemadeddu.sociallibraries W/System.err﹕ java.io.FileNotFoundException: /data/data/com.test.michelemadeddu.sociallibraries/databases/db_sociallibraries.db: open failed: ENOENT (No such file or directory) 02-09 01:28:46.384 24222-24222/com.test.michelemadeddu.sociallibraries W/System.err﹕ at libcore.io.IoBridge.open(IoBridge.java:409) 02-09 01:28:46.384 24222-24222/com.test.michelemadeddu.sociallibraries W/System.err﹕ at java.io.FileOutputStream.(FileOutputStream.java:88) 02-09 01:28:46.384 24222-24222/com.test.michelemadeddu.sociallibraries W/System.err﹕ at java.io.FileOutputStream.(FileOutputStream.java:128) 02-09 01:28:46.384 24222-24222/com.test.michelemadeddu.sociallibraries W/System.err﹕ at java.io.FileOutputStream.(FileOutputStream.java:117) 02-09 01:28:46.384 24222-24222/com.test.michelemadeddu.sociallibraries W/System.err﹕ at com.test.michelemadeddu.sociallibraries.DbHandler.checkCopyDb(DbHandler.java:44)

難道我做錯了什麼? 感謝

+0

是'c.getPackageName()'返回你期望的? – Prudhvi 2015-02-09 01:02:49

+0

是@prudhvi,我也試過明確寫包名,但結果是一樣的。事實上,如果你看看控制檯消息,它說錯誤在FileOutPutStream中,而不是InputStream – Michele 2015-02-09 01:07:50

+0

我所假設的是,你的文件不存在,所以你的'if'條件評估爲真。檢查該路徑中是否有該文件。 – Prudhvi 2015-02-09 01:21:26

回答

8

出於兼容性考慮,也許你可能會改變你的內部數據庫的路徑如下

if(android.os.Build.VERSION.SDK_INT >= 17) { 
    DB_PATH = context.getApplicationInfo().dataDir + "/databases/";   
} else { 
    DB_PATH = "/data/data/" + context.getPackageName() + "/databases/"; 
} 
1

請試試這個代碼... 這是我使用和正常工作。

只需替換DB_NAME,DATABASE_NAME和DB_PATH變量即可。

package your.packagename; 

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

import android.content.Context; 
import android.database.SQLException; 
import android.database.sqlite.SQLiteDatabase; 
import android.database.sqlite.SQLiteException; 
import android.database.sqlite.SQLiteOpenHelper; 
import android.util.Log; 

public class database extends SQLiteOpenHelper{ 

//The Android's default system path of your application database. 
private static String DB_PATH = "/data`/data/com.example.applicationame/databases/";` 

// Database Name 
private static String DB_NAME = "DB.sqlite"; 

// Logcat tag 
private static final String LOG = "database"; 

// Database Version 
private static final int DATABASE_VERSION = 1; 

// Database Name 
private static final String DATABASE_NAME = "DB.sqlite"; 

// Table Names 
private static final String TABLE_COUNTIES = "Counties"; 
private static final String TABLE_DESCRIPTIONS = "Descriptions"; 
private static final String TABLE_NEIGHBORHOODS = "Neighborhoods"; 

// Common column names 
private static final String KEY_ID = "_id"; 

// TABLE_COUNTIES Table - column names 
private static final String COL_COUNTYDETAIL = "countyDetail"; 
// TABLE_DESCRIPTIONS Table - column names 
private static final String COL_DESCRIPTIONDETAIL = "descriptionDetail"; 
// TABLE_NEIGHBORHOODS Table - column names 
private static final String COL_NEIGHBORHOODDETAIL = "neighborhoodDetail"; 

private SQLiteDatabase myDataBase; 

private final Context myContext; 

public static long INSERT_ERROR = -1; 
/** 
* Constructor 
* Takes and keeps a reference of the passed context in order to access to the application assets and resources. 
* @param context 
*/ 
public database(Context context) { 
    super(context, DATABASE_NAME, null, DATABASE_VERSION); 
    this.myContext = context; 

} 

/** 
* Creates a empty database on the system and rewrites it with your own database. 
* */ 
public void createDataBase() throws IOException{ 

    Log.d(LOG, "Calling checkDataBase() Method"); 

    boolean dbExist = checkDataBase(); 

    if(dbExist){ 
     //do nothing - database already exist 
     Log.d(LOG, "!!!Database Found!!!"); 
    }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. 
     Log.d(LOG, "!!!Creating Empy Database!!!"); 
     this.getReadableDatabase(); 
     this.close(); 
     try { 
      Log.d(LOG, "!!!Coping Database!!!"); 
      copyDataBase(); 
     } catch (IOException e) { 
      throw new Error(e); 
     } 
    } 
} 

/** 
* 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; 

     Log.d(LOG, "looking database at " + myPath); 

     checkDB = SQLiteDatabase.openDatabase(myPath, null, SQLiteDatabase.OPEN_READONLY); 

    }catch(SQLiteException e){ 
     //database does't exist yet. 
     Log.e(LOG, "Exception: 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; 

    Log.d(LOG, "Coping database from " + myInput + ", to " + outFileName); 

    //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{ 
    openDataBase(true); 
} 

public void openDataBase(boolean readonly) throws SQLException{ 
    //Open the database 
    String myPath = DB_PATH + DB_NAME; 

    if (readonly) 
     myDataBase = SQLiteDatabase.openDatabase(myPath, null, SQLiteDatabase.OPEN_READONLY); 
    else 
     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) { 
    // TODO Auto-generated method stub 

} 

@Override 
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { 
    // TODO Auto-generated method stub 

}  

} 

我希望它有幫助。 好運

相關問題