問題來源:android下的sqlite數據庫一般都是單機的,當一個應用中數據庫的數據多的時候,每換一個機子都重新配置一下數據庫中所有數據顯然是浪費時間的,所以最好的辦法就是可以訪問一個已經存在的數據庫。
解決方案:
方案一:在Eclipse中操作,僅僅限於模擬器使用。
步驟:
- 在Eclipse打開File Explorer視圖, File Explorer是用來查看設備的文件的, 打開方式爲在Eclipse中執行【Window】-【Show View】-【other】-【File Explorer】操作。
- 找到要導入文件的位置,也就是數據庫默認的位置/data/data/<包名>/database目錄。
- 選中目錄,然後點右上角位置的設備圖標【Pull a file from the device】,然後選擇要上傳的數據庫即可。
圖示如下:
方案二:將數據庫放到res/raw目錄下,在第一次數據訪問數據庫時拷貝紙/data/data/<包名>/database目錄下,模擬器和真機都適用。
拷貝的代碼如下:
try {
String filePath = context.getCacheDir().getAbsolutePath();
String DATABASE_PATH = filePath.substring(0, filePath.length() - 5)
+ "databases";
String DATABASE_FILENAME = "usmartscada.db";
String databaseFilename = DATABASE_PATH + "/" + DATABASE_FILENAME;
File dir = new File(DATABASE_PATH);
if (!dir.exists()) {
dir.mkdir();
}
if (!(new File(databaseFilename)).exists()) {
InputStream is = context.getResources().openRawResource(R.raw.usmartscada);;
FileOutputStream fos = new FileOutputStream(databaseFilename);
byte[] buffer = new byte[8192];
int count = 0;
// 開始複製文件
while ((count = is.read(buffer)) > 0) {
fos.write(buffer, 0, count);
}
fos.close();
is.close();
}
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
上面的代碼例子數據庫的名字爲usmartscada.db ,同時證明了複製進來的數據庫可以正常進行讀取和寫入,不存在權限不夠不能讀取和寫入的問題, 但是上面的代碼會有幾個問題。
爲什麼要把已存在數據庫文件放在res/raw文件夾下, 放在其它地方可以嗎?
如果放在res/raw文件夾下,數據庫文件在apk打包的時候就必須確定並且不可更改,否則每次都要重新編譯生成apk,在使用的時候會很麻煩,所以最好是將數據庫文件放置在sd卡的某個位置。經過驗證得知,數據庫文件可以放置到其它位置,例如sd卡的某個位置,至於放在什麼位置根據具體情景來覺得,上面的代碼只是一個例子而已,當然放在不同的位置,訪問文件的時候的方式也不一樣。當然注意要訪問sd卡的時候一定要在AndroidManifest.xml文件中添加訪問sd卡的權限。
- 上面的代碼沒有判斷已存在的數據庫文件是否存在?一是爲了代碼的嚴謹性考慮,二是因爲在特殊的機子上可能不需要之前已經存在的數據庫,希望自己配置並生成數據庫,此時就不需要複製之前的數據庫。
這個問題根據實際情景來決定是否需要判斷已存在的數據庫文件是否存在,判斷的時候根據數據庫文件放置的位置不同而不同,另外如果防止在res/raw文件夾下沒有辦法判斷數據庫文件是否存在,因爲訪問res/raw文件夾下的文件使用的方法是R.raw.xxx,如果文件不存在,沒辦法得到數據庫文件的對象,所以也就沒辦法判斷,補充一個知識res/raw文件夾下的文件的絕對路徑是”android.resource://”+ getPackageName() + R.raw.xxx。