Question

I am creating a Dictionary application which uses an existing sqlite database. I have placed my database in assets folder and I am using the following code to copy the database when the app is started for first time. (I have borrowed the idea from this post)

DatabaseHelper.java

public class DatabaseHelper {

private static String DB_PATH = "";
private static String DB_NAME = "abc.sqlite";
private SQLiteDatabase myDatabase;
private Context myContext;

public DatabaseHelper(Context context) {

    myContext = context;

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

public void copyDatabase() {

        InputStream myInput;
        OutputStream outStream;
        try {
            myInput = myContext.getAssets().open(DB_NAME);
            String file = DB_PATH + DB_NAME;
            outStream = new FileOutputStream(file);

            byte[] buffer = new byte[1024];
            int length = 0;
            while ((length = myInput.read(buffer)) >= 0) {
                outStream.write(buffer, 0, length);             
            }
            outStream.flush();
            myInput.close();
            outStream.close();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

    }
}

And then I call the above copyDatabase() method form my MainActivity. Here is the code.

public class MainActivity extends Activity {
    DatabaseHelper myDbHelper;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setContentView(R.layout.layout);
        myDbHelper = new DatabaseHelper(getApplicationContext());
        myDbHelper.copyDatabase();


    }

}

But the problem is that Android does not copy the database. I have used Log tool, and I found out that the while loop never runs. What's the problem in this code. Thanks.

Was it helpful?

Solution

Change your while loop as below:

Besides your condition >= greater than or equal to change it to only > Greater than

while ((length = myInput.read(buffer)) > 0) {
            outStream.write(buffer, 0, length);             
        }

Try out the below code which will work for you like charm.

public class DataBaseHelper extends SQLiteOpenHelper {
    private Context mycontext;
    private String DB_PATH; 

    private static String DB_NAME = "abc.sqlite";
    public SQLiteDatabase myDataBase;


    public DataBaseHelper(Context context) throws IOException {
        super(context,DB_NAME,null,1);
        this.mycontext=context;
        boolean dbexist = checkdatabase();
        if (dbexist) {
              opendatabase(); 
        } else {
            System.out.println("Database doesn't exist");
            createdatabase();
        }
    }

    public void createdatabase() throws IOException {
        boolean dbexist = checkdatabase();
        if(!dbexist) {
            this.getReadableDatabase();
            try {
                copydatabase();
            } catch(IOException e) {
                throw new Error("Error copying database");
            }
        }
    }   

    private boolean checkdatabase() {

        boolean checkdb = false;
        try {
            String myPath = DB_PATH + DB_NAME;
            File dbfile = new File(myPath);
            checkdb = dbfile.exists();
        } catch(SQLiteException e) {
            System.out.println("Database doesn't exist");
        }
        return checkdb;
    }

    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 byte to inputfile to 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_READWRITE);
    }

    public synchronized void close() {
        if(myDataBase != null) {
            myDataBase.close();
        }
        super.close();
    }

}

In your MainActivity you just now need to create and instance of your DatabaseHelper class others will managed on it own.

public class MainActivity extends Activity {
    DatabaseHelper myDbHelper;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setContentView(R.layout.layout);
        myDbHelper = new DatabaseHelper(MainActivity.this);
      }

}

OTHER TIPS

Change this from

while ((length = myInput.read(buffer)) >= 0) {
            outStream.write(buffer, 0, length);             
        }

to

while ((length = myInput.read(buffer)) >0) {
            outStream.write(buffer, 0, length);             
        }

Used this code for copy Database from assets folder

    public class DataBaseHelper extends SQLiteOpenHelper 
{ 
private static String TAG = "DataBaseHelper"; // Tag just for the LogCat window 
//destination path (location) of our database on device 
private static String DB_PATH = "";  
//private static String DB_NAME ="(students).sqlite";// Database name 
private static String DB_NAME ="virtualDB";
private SQLiteDatabase mDataBase;  
private final Context mContext; 

public DataBaseHelper(Context context)  
{ 
    super(context, DB_NAME, null, 1);// 1? its Database Version 
    DB_PATH = "/data/data/" + context.getPackageName() + "/databases/"; 
    Log.i(TAG, DB_PATH);
    this.mContext = context; 
}    

public void createDataBase() 
{ 
    //If database not exists copy it from the assets 

    boolean mDataBaseExist = checkDataBase(); 
    if(!mDataBaseExist) 
    { 
        this.getReadableDatabase(); 
        this.close(); 
        try  
        { 
            //Copy the database from assests 
            copyDataBase(); 
            Log.e(TAG, "createDatabase database created"); 
        }  
        catch (IOException mIOException)  
        { 
             Log.i(TAG, "createDataBase "+mIOException+"");
        } 
    } 
} 
    //Check that the database exists here: /data/data/your package/databases/Da Name 
    private boolean checkDataBase() 
    { 
        File dbFile = new File(DB_PATH + DB_NAME); 
        //Log.v("dbFile", dbFile + "   "+ dbFile.exists()); 
        return dbFile.exists(); 
    } 

    //Copy the database from assets 
    private void copyDataBase() throws IOException 
    {  try  
    { 
        InputStream mInput = mContext.getAssets().open(DB_NAME); 
        String outFileName = DB_PATH + DB_NAME; 
        OutputStream mOutput = new FileOutputStream(outFileName); 
        byte[] mBuffer = new byte[1024]; 
        int mLength; 
        while ((mLength = mInput.read(mBuffer))>0) 
        { 
            mOutput.write(mBuffer, 0, mLength); 
        } 
        mOutput.flush(); 
        mOutput.close(); 
        mInput.close(); 
    }  
    catch (IOException mIOException)  
    { Log.i(TAG,"copyDataBase "+ mIOException+"");

    } 
    } 

    //Open the database, so we can query it 
    public boolean openDataBase() throws SQLException 
    { 
        String mPath = DB_PATH + DB_NAME; 
        //Log.v("mPath", mPath); 
        mDataBase = SQLiteDatabase.openDatabase(mPath, null, SQLiteDatabase.CREATE_IF_NECESSARY); 
        //mDataBase = SQLiteDatabase.openDatabase(mPath, null, SQLiteDatabase.NO_LOCALIZED_COLLATORS); 
        return mDataBase != null; 
    } 

    @Override 
    public synchronized void close()  
    { 
        if(mDataBase != null) 
            mDataBase.close(); 
        super.close(); 
    }

    @Override
    public void onCreate(SQLiteDatabase arg0) {
        // TODO Auto-generated method stub

    }

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

    } 

} 

This code working fine for me I hope it help you

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top