--CREATE TABLE "kitchen_table"; This is one type of comment in sql. It is ignored by parseSql./** CREATE TABLE "coffee_table"; This is a second type of comment in sql. It is ignored by parseSql.*/{CREATE TABLE "pool_table"; This is a third type of comment in sql. It is ignored by parseSql.}/* CREATE TABLE "dining_room_table"; This is a second type of comment in sql. It is ignored by parseSql. */{ CREATE TABLE "card_table"; This is a third type of comment in sql. It is ignored by parseSql. }
--DROP TABLE "picnic_table"; Uncomment this if picnic table was previously created and now is being replaced.CREATE TABLE "picnic_table" ("plates" TEXT);INSERT INTO "picnic_table" VALUES ('paper');
package android.example;
import android.app.Activity;import android.database.sqlite.SQLiteDatabase;import android.os.Bundle;
/*** @author Danny Remington - MacroSolve** Activity for demonstrating how to use a sqlite database.*/public class Database extends Activity {/** Called when the activity is first created. */@Overridepublic void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.main);DatabaseHelper myDbHelper;SQLiteDatabase myDb = null;
myDbHelper = new DatabaseHelper(this);/** Database must be initialized before it can be used. This will ensure* that the database exists and is the current version.*/myDbHelper.initializeDataBase();
try {// A reference to the database can be obtained after initialization.myDb = myDbHelper.getWritableDatabase();/** Place code to use database here.*/} catch (Exception ex) {ex.printStackTrace();} finally {try {myDbHelper.close();} catch (Exception ex) {ex.printStackTrace();} finally {myDb.close();}}
}}
package android.example;
import java.io.FileOutputStream;import java.io.IOException;import java.io.InputStream;import java.io.OutputStream;
import android.content.Context;import android.database.sqlite.SQLiteDatabase;import android.database.sqlite.SQLiteOpenHelper;
/*** @author Danny Remington - MacroSolve** Helper class for sqlite database.*/public class DatabaseHelper extends SQLiteOpenHelper {
/** The Android's default system path of the application database in internal* storage. The package of the application is part of the path of the* directory.*/private static String DB_DIR = "/data/data/android.example/databases/";private static String DB_NAME = "database.sqlite";private static String DB_PATH = DB_DIR + DB_NAME;private static String OLD_DB_PATH = DB_DIR + "old_" + DB_NAME;
private final Context myContext;
private boolean createDatabase = false;private boolean upgradeDatabase = false;
/*** 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, context.getResources().getInteger(R.string.databaseVersion));myContext = context;// Get the path of the database that is based on the context.DB_PATH = myContext.getDatabasePath(DB_NAME).getAbsolutePath();}
/*** Upgrade the database in internal storage if it exists but is not current.* Create a new empty database in internal storage if it does not exist.*/public void initializeDataBase() {/** Creates or updates the database in internal storage if it is needed* before opening the database. In all cases opening the database copies* the database in internal storage to the cache.*/getWritableDatabase();
if (createDatabase) {/** If the database is created by the copy method, then the creation* code needs to go here. This method consists of copying the new* database from assets into internal storage and then caching it.*/try {/** Write over the empty data that was created in internal* storage with the one in assets and then cache it.*/copyDataBase();} catch (IOException e) {throw new Error("Error copying database");}} else if (upgradeDatabase) {/** If the database is upgraded by the copy and reload method, then* the upgrade code needs to go here. This method consists of* renaming the old database in internal storage, create an empty* new database in internal storage, copying the database from* assets to the new database in internal storage, caching the new* database from internal storage, loading the data from the old* database into the new database in the cache and then deleting the* old database from internal storage.*/try {FileHelper.copyFile(DB_PATH, OLD_DB_PATH);copyDataBase();SQLiteDatabase old_db = SQLiteDatabase.openDatabase(OLD_DB_PATH, null, SQLiteDatabase.OPEN_READWRITE);SQLiteDatabase new_db = SQLiteDatabase.openDatabase(DB_PATH,null, SQLiteDatabase.OPEN_READWRITE);/** Add code to load data into the new database from the old* database and then delete the old database from internal* storage after all data has been transferred.*/} catch (IOException e) {throw new Error("Error copying database");}}
}
/*** 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 {/** Close SQLiteOpenHelper so it will commit the created empty database* to internal storage.*/close();
/** Open the database in the assets folder as the input stream.*/InputStream myInput = myContext.getAssets().open(DB_NAME);
/** Open the empty db in interal storage as the output stream.*/OutputStream myOutput = new FileOutputStream(DB_PATH);
/** Copy over the empty db in internal storage with the database in the* assets folder.*/FileHelper.copyFile(myInput, myOutput);
/** Access the copied database so SQLiteHelper will cache it and mark it* as created.*/getWritableDatabase().close();}
/** This is where the creation of tables and the initial population of the* tables should happen, if a database is being created from scratch instead* of being copied from the application package assets. Copying a database* from the application package assets to internal storage inside this* method will result in a corrupted database.* <P>* NOTE: This method is normally only called when a database has not already* been created. When the database has been copied, then this method is* called the first time a reference to the database is retrieved after the* database is copied since the database last cached by SQLiteOpenHelper is* different than the database in internal storage.*/@Overridepublic void onCreate(SQLiteDatabase db) {/** Signal that a new database needs to be copied. The copy process must* be performed after the database in the cache has been closed causing* it to be committed to internal storage. Otherwise the database in* internal storage will not have the same creation timestamp as the one* in the cache causing the database in internal storage to be marked as* corrupted.*/createDatabase = true;
/** This will create by reading a sql file and executing the commands in* it.*/// try {// InputStream is = myContext.getResources().getAssets().open(// "create_database.sql");//// String[] statements = FileHelper.parseSqlFile(is);//// for (String statement : statements) {// db.execSQL(statement);// }// } catch (Exception ex) {// ex.printStackTrace();// }}
/*** Called only if version number was changed and the database has already* been created. Copying a database from the application package assets to* the internal data system inside this method will result in a corrupted* database in the internal data system.*/@Overridepublic void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {/** Signal that the database needs to be upgraded for the copy method of* creation. The copy process must be performed after the database has* been opened or the database will be corrupted.*/upgradeDatabase = true;
/** Code to update the database via execution of sql statements goes* here.*/
/** This will upgrade by reading a sql file and executing the commands in* it.*/// try {// InputStream is = myContext.getResources().getAssets().open(// "upgrade_database.sql");//// String[] statements = FileHelper.parseSqlFile(is);//// for (String statement : statements) {// db.execSQL(statement);// }// } catch (Exception ex) {// ex.printStackTrace();// }}
/*** Called everytime the database is opened by getReadableDatabase or* getWritableDatabase. This is called after onCreate or onUpgrade is* called.*/@Overridepublic void onOpen(SQLiteDatabase db) {super.onOpen(db);}
/** 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.*/
}
这是FileHelper类,它包含用于字节流复制文件和解析sql文件的方法。
package android.example;
import java.io.BufferedReader;import java.io.File;import java.io.FileInputStream;import java.io.FileOutputStream;import java.io.FileReader;import java.io.IOException;import java.io.InputStream;import java.io.InputStreamReader;import java.io.OutputStream;import java.io.Reader;import java.nio.channels.FileChannel;
/*** @author Danny Remington - MacroSolve** Helper class for common tasks using files.**/public class FileHelper {/*** Creates the specified <i><b>toFile</b></i> that is a byte for byte a copy* of <i><b>fromFile</b></i>. If <i><b>toFile</b></i> already existed, then* it will be replaced with a copy of <i><b>fromFile</b></i>. The name and* path of <i><b>toFile</b></i> will be that of <i><b>toFile</b></i>. Both* <i><b>fromFile</b></i> and <i><b>toFile</b></i> will be closed by this* operation.** @param fromFile* - InputStream for the file to copy from.* @param toFile* - InputStream for the file to copy to.*/public static void copyFile(InputStream fromFile, OutputStream toFile) throws IOException {// transfer bytes from the inputfile to the outputfilebyte[] buffer = new byte[1024];int length;
try {while ((length = fromFile.read(buffer)) > 0) {toFile.write(buffer, 0, length);}}// Close the streamsfinally {try {if (toFile != null) {try {toFile.flush();} finally {toFile.close();}}} finally {if (fromFile != null) {fromFile.close();}}}}
/*** Creates the specified <i><b>toFile</b></i> that is a byte for byte a copy* of <i><b>fromFile</b></i>. If <i><b>toFile</b></i> already existed, then* it will be replaced with a copy of <i><b>fromFile</b></i>. The name and* path of <i><b>toFile</b></i> will be that of <i><b>toFile</b></i>. Both* <i><b>fromFile</b></i> and <i><b>toFile</b></i> will be closed by this* operation.** @param fromFile* - String specifying the path of the file to copy from.* @param toFile* - String specifying the path of the file to copy to.*/public static void copyFile(String fromFile, String toFile) throws IOException {copyFile(new FileInputStream(fromFile), new FileOutputStream(toFile));}
/*** Creates the specified <i><b>toFile</b></i> that is a byte for byte a copy* of <i><b>fromFile</b></i>. If <i><b>toFile</b></i> already existed, then* it will be replaced with a copy of <i><b>fromFile</b></i>. The name and* path of <i><b>toFile</b></i> will be that of <i><b>toFile</b></i>. Both* <i><b>fromFile</b></i> and <i><b>toFile</b></i> will be closed by this* operation.** @param fromFile* - File for the file to copy from.* @param toFile* - File for the file to copy to.*/public static void copyFile(File fromFile, File toFile) throws IOException {copyFile(new FileInputStream(fromFile), new FileOutputStream(toFile));}
/*** Creates the specified <i><b>toFile</b></i> that is a byte for byte a copy* of <i><b>fromFile</b></i>. If <i><b>toFile</b></i> already existed, then* it will be replaced with a copy of <i><b>fromFile</b></i>. The name and* path of <i><b>toFile</b></i> will be that of <i><b>toFile</b></i>. Both* <i><b>fromFile</b></i> and <i><b>toFile</b></i> will be closed by this* operation.** @param fromFile* - FileInputStream for the file to copy from.* @param toFile* - FileInputStream for the file to copy to.*/public static void copyFile(FileInputStream fromFile, FileOutputStream toFile) throws IOException {FileChannel fromChannel = fromFile.getChannel();FileChannel toChannel = toFile.getChannel();
try {fromChannel.transferTo(0, fromChannel.size(), toChannel);} finally {try {if (fromChannel != null) {fromChannel.close();}} finally {if (toChannel != null) {toChannel.close();}}}}
/*** Parses a file containing sql statements into a String array that contains* only the sql statements. Comments and white spaces in the file are not* parsed into the String array. Note the file must not contained malformed* comments and all sql statements must end with a semi-colon ";" in order* for the file to be parsed correctly. The sql statements in the String* array will not end with a semi-colon ";".** @param sqlFile* - String containing the path for the file that contains sql* statements.** @return String array containing the sql statements.*/public static String[] parseSqlFile(String sqlFile) throws IOException {return parseSqlFile(new BufferedReader(new FileReader(sqlFile)));}
/*** Parses a file containing sql statements into a String array that contains* only the sql statements. Comments and white spaces in the file are not* parsed into the String array. Note the file must not contained malformed* comments and all sql statements must end with a semi-colon ";" in order* for the file to be parsed correctly. The sql statements in the String* array will not end with a semi-colon ";".** @param sqlFile* - InputStream for the file that contains sql statements.** @return String array containing the sql statements.*/public static String[] parseSqlFile(InputStream sqlFile) throws IOException {return parseSqlFile(new BufferedReader(new InputStreamReader(sqlFile)));}
/*** Parses a file containing sql statements into a String array that contains* only the sql statements. Comments and white spaces in the file are not* parsed into the String array. Note the file must not contained malformed* comments and all sql statements must end with a semi-colon ";" in order* for the file to be parsed correctly. The sql statements in the String* array will not end with a semi-colon ";".** @param sqlFile* - Reader for the file that contains sql statements.** @return String array containing the sql statements.*/public static String[] parseSqlFile(Reader sqlFile) throws IOException {return parseSqlFile(new BufferedReader(sqlFile));}
/*** Parses a file containing sql statements into a String array that contains* only the sql statements. Comments and white spaces in the file are not* parsed into the String array. Note the file must not contained malformed* comments and all sql statements must end with a semi-colon ";" in order* for the file to be parsed correctly. The sql statements in the String* array will not end with a semi-colon ";".** @param sqlFile* - BufferedReader for the file that contains sql statements.** @return String array containing the sql statements.*/public static String[] parseSqlFile(BufferedReader sqlFile) throws IOException {String line;StringBuilder sql = new StringBuilder();String multiLineComment = null;
while ((line = sqlFile.readLine()) != null) {line = line.trim();
// Check for start of multi-line commentif (multiLineComment == null) {// Check for first multi-line comment typeif (line.startsWith("/*")) {if (!line.endsWith("}")) {multiLineComment = "/*";}// Check for second multi-line comment type} else if (line.startsWith("{")) {if (!line.endsWith("}")) {multiLineComment = "{";}// Append line if line is not empty or a single line comment} else if (!line.startsWith("--") && !line.equals("")) {sql.append(line);} // Check for matching end comment} else if (multiLineComment.equals("/*")) {if (line.endsWith("*/")) {multiLineComment = null;}// Check for matching end comment} else if (multiLineComment.equals("{")) {if (line.endsWith("}")) {multiLineComment = null;}}
}
sqlFile.close();
return sql.toString().split(";");}
}
Copy the database into the assets directory, in a subdirectory called assets/databases. For instance: assets/databases/my_database.db
(Optionally, you may compress the database in a zip file such as assets/databases/my_database.zip. This isn't needed, since the APK is compressed as a whole already.)
Create a class, for example:
public class MyDatabase extends SQLiteAssetHelper {
private static final String DATABASE_NAME = "my_database.db";private static final int DATABASE_VERSION = 1;
public MyDatabase(Context context) {super(context, DATABASE_NAME, null, DATABASE_VERSION);}}
package farhangsarasIntroduction;
import java.io.File;import java.io.FileOutputStream;import java.io.IOException;import java.io.InputStream;import java.io.OutputStream;import java.util.ArrayList;import java.util.HashMap;
import android.content.Context;import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;import android.database.sqlite.SQLiteException;import android.database.sqlite.SQLiteOpenHelper;
import android.util.Log;
public class DataBaseHelper extends SQLiteOpenHelper{
//The Android's default system path of your application database.private static String DB_PATH = "data/data/com.example.sample/databases";
private static String DB_NAME = "farhangsaraDb";
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() {
boolean dbExist;try {
dbExist = checkDataBase();
} catch (SQLiteException e) {
e.printStackTrace();throw new Error("database dose not exist");
}
if(dbExist){//do nothing - database already exist}else{
try {
copyDataBase();
} catch (IOException e) {
e.printStackTrace();throw new Error("Error copying database");
}//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();
}
}
/*** 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 does't exist yet.throw new Error("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{
//copyDataBase();//Open your local db as the input streamInputStream myInput = myContext.getAssets().open(DB_NAME);
// Path to the just created empty dbString outFileName = DB_PATH +"/"+ DB_NAME;File databaseFile = new File( DB_PATH);// check if databases folder exists, if not create one and its subfoldersif (!databaseFile.exists()){databaseFile.mkdir();}
//Open the empty db as the output streamOutputStream myOutput = new FileOutputStream(outFileName);
//transfer bytes from the inputfile to the outputfilebyte[] buffer = new byte[1024];int length;while ((length = myInput.read(buffer))>0){myOutput.write(buffer, 0, length);}
//Close the streamsmyOutput.flush();myOutput.close();myInput.close();
}
@Overridepublic synchronized void close() {
if(myDataBase != null)myDataBase.close();
super.close();
}
@Overridepublic void onCreate(SQLiteDatabase db) {
}
@Overridepublic void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
}
you to create adapters for your views.
}
public class PlanDetailsSQLiteOpenHelper extends SQLiteOpenHelper {private static final String TAG = "SQLiteOpenHelper";
private final Context context;private static final int DATABASE_VERSION = 1;private static final String DATABASE_NAME = "my_custom_db";
private boolean createDb = false, upgradeDb = false;
public PlanDetailsSQLiteOpenHelper(Context context) {super(context, DATABASE_NAME, null, DATABASE_VERSION);this.context = context;}
/*** Copy packaged database from assets folder to the database created in the* application package context.** @param db* The target database in the application package context.*/private void copyDatabaseFromAssets(SQLiteDatabase db) {Log.i(TAG, "copyDatabase");InputStream myInput = null;OutputStream myOutput = null;try {// Open db packaged as asset as the input streammyInput = context.getAssets().open("path/to/shipped/db/file");
// Open the db in the application package context:myOutput = new FileOutputStream(db.getPath());
// Transfer db file contents:byte[] buffer = new byte[1024];int length;while ((length = myInput.read(buffer)) > 0) {myOutput.write(buffer, 0, length);}myOutput.flush();
// Set the version of the copied database to the current// version:SQLiteDatabase copiedDb = context.openOrCreateDatabase(DATABASE_NAME, 0, null);copiedDb.execSQL("PRAGMA user_version = " + DATABASE_VERSION);copiedDb.close();
} catch (IOException e) {e.printStackTrace();throw new Error(TAG + " Error copying database");} finally {// Close the streamstry {if (myOutput != null) {myOutput.close();}if (myInput != null) {myInput.close();}} catch (IOException e) {e.printStackTrace();throw new Error(TAG + " Error closing streams");}}}
@Overridepublic void onCreate(SQLiteDatabase db) {Log.i(TAG, "onCreate db");createDb = true;}
@Overridepublic void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {Log.i(TAG, "onUpgrade db");upgradeDb = true;}
@Overridepublic void onOpen(SQLiteDatabase db) {Log.i(TAG, "onOpen db");if (createDb) {// The db in the application package// context is being created.// So copy the contents from the db// file packaged in the assets// folder:createDb = false;copyDatabaseFromAssets(db);
}if (upgradeDb) {// The db in the application package// context is being upgraded from a lower to a higher version.upgradeDb = false;// Your db upgrade logic here:}}}
//get context by calling "this" in activity or getActivity() in fragment//call this if API level is lower than 17 String appDataPath = "/data/data/" + context.getPackageName() + "/databases/"String appDataPath = context.getApplicationInfo().dataDir;
File dbFolder = new File(appDataPath + "/databases");//Make sure the /databases folder existsdbFolder.mkdir();//This can be called multiple times.
File dbFilePath = new File(appDataPath + "/databases/testDB.db");
try {InputStream inputStream = context.getAssets().open("testDB.db");OutputStream outputStream = new FileOutputStream(dbFilePath);byte[] buffer = new byte[1024];int length;while ((length = inputStream.read(buffer))>0){outputStream.write(buffer, 0, length);}outputStream.flush();outputStream.close();inputStream.close();} catch (IOException e){//handle}
Room.databaseBuilder(context.applicationContext,DataDatabase::class.java, "Sample.db")// prepopulate the database after onCreate was called.addCallback(object : Callback() {override fun onCreate(db: SupportSQLiteDatabase) {super.onCreate(db)// moving to a new threadioThread {getInstance(context).dataDao().insert(PREPOPULATE_DATA)}}}).build()