我不明白为什么我无法将我的db文件(abic_)复制到应用程序目录(“/ data / data /”+ context.getPackageName()+“/ databases”)
这是我的DataBaseHelper类:
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.IOException;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;
public class DataBaseHelper extends SQLiteOpenHelper{
//The Android's default system path of your application database.
private String DB_PATH;
private static String DB_NAME = "abic_";
private static final Integer DB_VERSION = 1;
private SQLiteDatabase mydb;
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, DB_VERSION);
this.myContext = context;
DB_PATH = "/data/data/" + context.getPackageName() + "/databases";
}
@Override
public void onCreate(SQLiteDatabase db) {;
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
}
public void apriDatabase() throws SQLException {
try {
String percorso = DB_PATH + DB_NAME;
mydb = SQLiteDatabase.openDatabase(percorso, null, SQLiteDatabase.OPEN_READONLY);
} catch (Exception e) {
e.printStackTrace();
}
}
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) {
e.printStackTrace();
}
}
}
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;
// if the path doesn't exist first, create it
File f = new File(outFileName);
if (!f.exists()){
f.mkdir();
f.createNewFile();
}
//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 boolean checkDataBase(){
SQLiteDatabase checkDB = null;
try{
String myPath = DB_PATH + DB_NAME;
checkDB = SQLiteDatabase.openDatabase(myPath, null, SQLiteDatabase.OPEN_READWRITE);
}catch(SQLiteException e){
//database does't exist yet.
}
if(checkDB != null){
checkDB.close();
}
return checkDB != null ? true : false;
}
@Override
public synchronized void close() {
if(mydb != null)
mydb.close();
super.close();
}
}
这是使用此类的列表视图:
import android.app.ListActivity;
import android.content.Intent;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.os.Bundle;
import android.view.View;
import android.widget.EditText;
import android.widget.ListAdapter;
import android.widget.ListView;
import android.widget.SimpleCursorAdapter;
public class abicabList extends ListActivity {
protected EditText searchText;
protected SQLiteDatabase mydb;
protected Cursor cursor;
protected ListAdapter adapter;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
mydb = (new DataBaseHelper(this)).getWritableDatabase();
searchText = (EditText) findViewById (R.id.searchText);
}
public void search(View view) {
String text = searchText.getText().toString();
String cap = "CAP";
// || is the concatenation operation in SQLite
if (text.length()14) {
cursor = mydb.rawQuery("SELECT _id, ABI, BANCA, CAB, CAP, Filiale, City FROM abicab WHERE ABI || CAB LIKE ? LIMIT 30",
new String[]{"%" + searchText.getText().toString().substring(6,10) + "%" + searchText.getText().toString().substring(11,15) + "%"});
adapter = new SimpleCursorAdapter(
this,
R.layout.abicab_list_item,
cursor,
new String[] {"BANCA", "Filiale", "City", "CAP"},
new int[] {R.id.BANCA, R.id.Filiale, R.id.City ,R.id.CAP});
setListAdapter(adapter);
}
}
因此,当我运行应用程序时,db在文件夹中创建,但它不包含我在资产文件夹中的数据库中的表(参见图片[1]:http://i.stack.imgur.com/AaFj8.jpg)。 在此先感谢您的帮助。
答案 0 :(得分:3)
我已经解决了这个问题。
1)我使用了Almanac 0.0.17(开源项目)中使用的AlmanacSQLiteDatabaseAdapter.java类,您可以在这里找到: link。您可以满足您的需求(在我的情况下,我已经重命名为DatabaseHelper);
2)这是使用Helper的类(它是一个listview,它在EditText中执行sql rawquery读取字符串 - 这是本教程“coenraets.org/blog/android-samples/androidtutorial/”的安排:
public class MiaList extends Activity {
protected EditText searchText;
protected SQLiteDatabase db;
protected Cursor cursor;
protected ListAdapter ladapter;
protected ListView miaList;
private static final String DATABASE_NAME = "miodb.jpg";
/*
L'ESTENSIONE JPG (o mp3, mov) questo perchè android ha il limite di 1 mb per i file di testo
o simili nella asset, mentre NON HA limiti per i file multimediali! Nel mio caso si tratta di 4mb
*/
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
//qui sotto richiamo la classe DatabaseHelper
DatabaseHelper dbAdapter = DatabaseHelper.getInstance(this, DATABASE_NAME);
/*note di Vytek*/
// OK Dovrei usare aSQLiteDatabaseAdapter.getDatabase(); ma questo crea
// problemi nella fase di OnPause quando premo Back cosi' invece non
// ottengo errori
// e viene fatta la normale copia del DB (13/8/2010 23.18)
// db = aSQLiteDatabaseAdapter.getWritableDatabase();
// Per ovviare a questo problema controllo se e' la prima volta che
// chiamo applicazione
if (getFirstRun()) {
db = dbAdapter.getDatabase();
setRunned();
} else {
db = dbAdapter.getWritableDatabase();
}
searchText = (EditText) findViewById (R.id.searchText);
miaList = (ListView) findViewById (R.id.list);
}
private void setRunned() {
// TODO Auto-generated method stub
}
private boolean getFirstRun() {
// TODO Auto-generated method stub
return false;
}
public void search(View view) {
String text = searchText.getText().toString();
// || è l'operatore "concatena" in SQLite
if (text.length()<15){
cursor = db.rawQuery("SELECT *FROM miatable WHERE AAA || ' ' || BBB || ' ' || CCC LIKE ? LIMIT 30",
new String[]{"%" + searchText.getText().toString() + "%"});
ladapter = new SimpleCursorAdapter(
this,
R.layout.mialist_list_item,
cursor,
new String[] {"_id", "AAA", "BBB", "CCC"},
new int[] {R.id._id, R.id.AAA, R.id.BBB, R.id.CCC});
miaList.setAdapter(ladapter);
//istruzione da eseguire
}
else {
cursor = db.rawQuery("SELECT * FROM miatable WHERE AAA || BBB LIKE ? LIMIT 30",
new String[]{"%" + searchText.getText().toString().substring(6,10) + "%" + searchText.getText().toString().substring(11,15) + "%"});
ladapter = new SimpleCursorAdapter(
this,
R.layout.mialist_list_item,
cursor,
new String[] {"_id", "AAA", "BBB", "CCC"},
new int[] {R.id._id, R.id.AAA, R.id.BBB, R.id.CCC});
miaList.setAdapter(ladapter);
//istruzione da eseguire
}
}
}
当然,SQLite DB“miodb.jpg”必须位于eclipse工作区的资产文件夹中。
<强> PS 强> 我使用了jpg扩展名,因为资产文件夹对db或txt或xml扩展名有1Mb限制。
答案 1 :(得分:2)
您使用的是仿真器还是设备?
我做了同样的程序但是我将数据库复制到SD卡中,因为模拟器的空间大小有限,数据库的大小是多少?
用这个替换你的副本方法,让我知道,因为除了复制方法,我找不到任何奇怪的东西,祝你好运。
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();
}
答案 2 :(得分:2)
首先确保将android.permission.WRITE_EXTERNAL_STORAGE权限添加到清单文件中。 在我的一个应用程序中,我使用下面的类,它完美地工作。试试这个,让我知道它是否有效。
public class ImpotDatabaseFileTask extends AsyncTask<String, Void, Boolean> {
ProgressDialog dialog;
private Context con;
boolean success = false;
public ImpotDatabaseFileTask(Context con) {
this.con = con;
dialog = new ProgressDialog(con);
this.dialog.setMessage("Importing database...");
execute(null);
}
@Override
protected Boolean doInBackground(String... params) {
try {
OutputStream myOutput;
File destination = new File(Environment.getDataDirectory()
+ "//data//<package name>//databases//database_name.db");
// Set the folder on the SDcard
File dbFile = new File(Environment.getExternalStorageDirectory(),
"//<custom folder>//<database_name>.db");
if (dbFile.exists()) {
copyFile(dbFile, destination);
success = true;
}
} catch (FileNotFoundException e) {
// Toast.makeText(Settings.this,
// "Restore unsuccessful! File not found! Directory does not exist?",
// Toast.LENGTH_LONG).show();
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
Toast.makeText(con, "Restore unsuccessful!", Toast.LENGTH_SHORT)
.show();
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
void copyFile(File src, File dst) throws IOException {
FileChannel inChannel = new FileInputStream(src).getChannel();
FileChannel outChannel = new FileOutputStream(dst).getChannel();
try {
inChannel.transferTo(0, inChannel.size(), outChannel);
} finally {
if (inChannel != null)
inChannel.close();
if (outChannel != null)
outChannel.close();
}
}
@Override
protected void onPostExecute(Boolean result) {
if (this.dialog.isShowing()) {
this.dialog.dismiss();
}
if (success) {
Toast.makeText(con, "Restore successful!", Toast.LENGTH_SHORT)
.show();
} else {
Toast.makeText(con, "Restore failed", Toast.LENGTH_SHORT).show();
}
super.onPostExecute(result);
}
}
答案 3 :(得分:0)
以下是我使用的简单方便的代码:
public class DataBaseImportHelper {
private DataBaseImportHelper() {}; // Avoid instantiation
/**
* Creates a empty database on the system and rewrites it with your own database.
*/
public static boolean importDataBase(Context context) {
InputStream myInput = null;
OutputStream myOutput = null;
try {
// Open local db from assets as the input stream
myInput = context.getAssets().open(DATABASE_NAME);
createEmptyDatabase(context); // See this method below
// Open the empty db as the output stream
myOutput = new FileOutputStream(getDatabaseFile(context));
// 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();
myInput.close();
myOutput.close();
return true;
} catch (IOException e) {
e.printStackTrace();
}
return false;
}
/**
* Check if the database already exists.
* @return true if it exists, false if it doesn't
*/
public static boolean isDatabaseExists(Context context) {
return getDatabaseFile(context).exists();
}
private static File getDatabaseFile(Context context) {
return context.getDatabasePath(DatabaseHelper.DATABASE_NAME);
}
/**
* Create an empty database into the default application database
* folder.So we are gonna be able to overwrite that database with our database
*/
private static void createEmptyDatabase(Context context) {
// use anonimous helper to create empty database
new SQLiteOpenHelper(context, DatabaseHelper.DATABASE_NAME, null, 1) {
// Methods are empty. We don`t need to override them
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
}
@Override
public void onCreate(SQLiteDatabase db) {
}
}.getReadableDatabase().close();
}
}
在代码中使用:
if(!DataBaseImportHelper.isDatabaseExists(this)){
if (!DataBaseImportHelper.importDataBase(this)){
throw new IllegalStateException("Database doesn`t exist and hasn`t been copied!");
}
}