android 如何实现附加现有数据库?而不是每次安装的时候都创建新的数据库。 
   最近做一个应用,在数据库中要内置很多数据,但有不想在每次安装的时候都重新创建数据库并插入数据,原因是插入数据时间较长,用户体验不好,所以特地想问问大家,有没有什么办法,让我一次吧数据库的内容都填充好,再以后的安装过程中不用再重新创建数据库了,类似sqlserver中的附加数据库!

解决方案 »

  1.   

    我是指安装apk的时候。能不能把已有的数据库附到apk包中
      

  2.   

    http://topic.csdn.net/u/20101123/17/7ced9a3c-7d6a-4478-ae19-1b37136d40b5.html?91014
      

  3.   

    仍旧不是我想要的,上面的文章讲的是如何不覆盖安装。而我的需求是在第一安装的时候,apk中的数据库包含有数据。而不是在安装的时候先创建数据库,创建表,然后再插入数据。
      

  4.   

    public class DataBase extends SQLiteOpenHelper {
        public DataBase(Context context) {
                // 创建一个名为realcode_tes的数据库
                super(context, "realcode_tes", null,3);
        }3这个参数指的是数据库的版本,你下次安装如果你的新程序还是3则不会再创建数据库,会保留你之前的数据而覆盖安装是指在文件管理里面的安装才能实现,通过其他方式安装好像都是卸载后重新安装
      

  5.   


    哦,你的意思是不是说,把数据库文件直接打包到apk中,然后程序里就不创建了,直接去读取这个数据库文件?
    如果是这样,那可以把数据库文件xx.db,放在assets目录,程序中访问:
            AssetManager am = context.getAssets();  
            InputStream is = am.open(fileName);  
      

  6.   

    能不能给个实例啊,我现在是复制到sdcard上了,但是每次打开的时候数据库都是空的
    SQLiteDatabase database = SQLiteDatabase.openOrCreateDatabase(databaseFilename, null);   //打开数据库
    databaseFilename="/sdcard/crazynovel/crazynovel.db" //这是路径在数据库类中的open中打开现有数据库

    private class DatabaseHelper extends SQLiteOpenHelper
    {
    DatabaseHelper(Context context) 
    {
    super(context, DATABASE_NAME, null, DATABASE_VERSION);

    }
    ...
    }
    public DbControl open() throws SQLException 
    {
    // mDbHelper = new DatabaseHelper(mCtx);
    // db = mDbHelper.getWritableDatabase();
    copyDb co = new copyDb(mCtx);
    db = co.openDatabase();   //这里是打开数据库的方法调用,现在没法调用getWritableDatabase();方法了}
      

  7.   

    SQLiteDatabase database = SQLiteDatabase.openOrCreateDatabase(databaseFilename, null); //打开数据库
    databaseFilename="/sdcard/crazynovel/crazynovel.db" //这是路径
    你这个是创建一个数据库,并不是打开你资源文件里面的数据库,当然是空的。
    建议:先将你的数据库里面的数据处理好,放到你的资源文件夹下面,比如asset或则res-raw(这个得自己创建),然后通过文件流的方式将其写到你的手机上面,不管是sdcard还是内存。然后再打开这个数据库即可。
      

  8.   

    你去查看android的APK备份机制吧,APK里代码和用户数据是可以分别设置是否备份的,
    这里你就备份个数据库文件就可以了,下次安装就只要更新APK里代码就OK了,
    具体我也没实现,你可以按照这个思路去查查资料,网上有很多的。
      

  9.   

    这个我做过,谈下经验。你可以先拿工具做个数据库,在windows下有做sqlite数据库的图形界面工具。我用的sqliteadmin。把你做好的数据库放在asset目录下或者res/raw目录下,然后程序一开始就检查data目录下是否存在数据库,不存在就把你的数据库拷到data目录下,存在的话就可以直接操作数据库了。当然你可以把你的数据库放在任意你想放的地方,比如sd卡。这样你的程序只在第一次运行的时候会拷贝数据库,以后就直接读库,不会有拷贝的操作,程序反应就很快了。
    其实我对楼主的问题有个疑问,即使是程序创建数据库,也不是每次启动就插数据啊。你程序第一次启动就会在默认目录下创建数据库并初始化(如果你有初始化动作的话),以后也是在此基础上进行增删查找的。难道你的程序每次关闭的时候都干掉数据库?不懂,求解。
      

  10.   

    看这里
    http://www.cnblogs.com/zhegebucuo/archive/2010/09/11/1823964.html
      

  11.   

    问题已经解决。给个大家个结果
    就是先将数据库存到raw上,然后在第一次安装的时候复制到sdcard上,以后就直接打开数据库了。
    一下是代码:  private Context context; 
     private String rootDirectory = "/data/data/CrazyNovelV1_0.com/data/";
     private final String DATABASE_PATH = android.os.Environment.getExternalStorageDirectory().getAbsolutePath()
         + "/crazynovel";
     private final String DATABASE_FILENAME = "crazynovel.db";//复制小于1M的数据库程序     
        public SQLiteDatabase openDatabase()   
        {   
            try  
            {   
                // 获得dictionary.db文件的绝对路径   
                String databaseFilename = DATABASE_PATH+ "/" + DATABASE_FILENAME;   
                File dir = new File(DATABASE_PATH);   
                // 如果/sdcard/dictionary目录不中存在,创建这个目录   
                if (!dir.exists())   
                    dir.mkdir();   
                // 如果在/sdcard/dictionary目录中不存在   
                // dictionary.db文件,则从res\raw目录中复制这个文件到   
                // SD卡的目录(/sdcard/dictionary)   
                if (!(new File(databaseFilename)).exists())   
                {   
                    // 获得封装dictionary.db文件的InputStream对象   
                    InputStream is = context.getResources().openRawResource(R.raw.crazynovel);   
                    FileOutputStream fos = new FileOutputStream(databaseFilename);   
                    byte[] buffer = new byte[7168];   
                    int count = 0;   
                    // 开始复制dictionary.db文件   
                    while ((count = is.read(buffer)) > 0)   
                    {   
                        fos.write(buffer, 0, count);   
                    }   
                    fos.close();   
                    is.close();   
                }   
                // 打开/sdcard/dictionary目录中的dictionary.db文件   
                SQLiteDatabase database = SQLiteDatabase.openOrCreateDatabase(databaseFilename, null);   
                return database;   
            }   
            catch (Exception e)   
            {   
            }   
        }  
    小于1M的可以用上面的方法复制,但是如果文件大于1M则不行,需要分割后再合并,最终拷贝到sdcard上。现在还没实现,等我实现了再贴上。如果哪位大侠这道可帮一把。
      

  12.   

    请教下楼主,为什么我用SQLiteDatabase database = SQLiteDatabase.openOrCreateDatabase(
                        databaseFilename, null);
    得到的database  是null呢?
      

  13.   


    空可能是应为路径不对吧,或者是的的数据库有问题,下载到本地后用SQLiteSpy.exe工具看看,能不能打开。
      

  14.   

    今天来结贴,顺便把我的解决方法给大家做个参考。
    首先用文件分割器把数据库分割为小于1M的文件,并拷贝到raw下,然后就是在程序里把文件拷贝到sdcard卡上,并把分割后的文件合并成数据库文件。代码如下:private Context context; 
         private String rootDirectory = "/data/data/CrazyNovelV1_0.com/data/";
         private final String DATABASE_PATH = android.os.Environment.getExternalStorageDirectory().getAbsolutePath()
         + "/crazynovel";
         private final String DATABASE_FILENAME = "crazynovel.db";//复制小于1M的数据库程序        
            public SQLiteDatabase openDatabase()   
            {   
                try  
                {   
                    // 获得dictionary.db文件的绝对路径   
                    String databaseFilename = DATABASE_PATH+ "/" + DATABASE_FILENAME;   
                    File dir = new File(DATABASE_PATH);   
                    // 如果/sdcard/dictionary目录不中存在,创建这个目录   
                    if (!dir.exists())   
                        dir.mkdir();   
                    // 如果在/sdcard/dictionary目录中不存在   
                    // dictionary.db文件,则从res\raw目录中复制这个文件到   
                    // SD卡的目录(/sdcard/dictionary)   
                 if (!(new File(databaseFilename)).exists())   
                {   
                 //复制文件
                 copydb(R.raw.crazynovel1,DATABASE_PATH+ "/crazynovel1",944128);
                 copydb(R.raw.crazynovel2,DATABASE_PATH+ "/crazynovel2",944128);
                 copydb(R.raw.crazynovel3,DATABASE_PATH+ "/crazynovel3",944128);
                 copydb(R.raw.crazynovel4,DATABASE_PATH+ "/crazynovel4",944128);
                 copydb(R.raw.crazynovel5,DATABASE_PATH+ "/crazynovel5",944128);
                 copydb(R.raw.crazynovel6,DATABASE_PATH+ "/crazynovel6",944128);
                 copydb(R.raw.crazynovel7,DATABASE_PATH+ "/crazynovel7",944128);
                 copydb(R.raw.crazynovel8,DATABASE_PATH+ "/crazynovel8",944128);
                 copydb(R.raw.crazynovel9,DATABASE_PATH+ "/crazynovel9",944128);
                 copydb(R.raw.crazynovel10,DATABASE_PATH+ "/crazynovel10",944128);
                 copydb(R.raw.crazynovel11,DATABASE_PATH+ "/crazynovel11",944128);
                 copydb(R.raw.crazynovel12,DATABASE_PATH+ "/crazynovel12",669696);
                
                 //合并文件
                 File[] files = new File[12];
                 files[0] = new File(DATABASE_PATH+ "/crazynovel1");
                 files[1] = new File(DATABASE_PATH+ "/crazynovel2");
                 files[2] = new File(DATABASE_PATH+ "/crazynovel3");
                 files[3] = new File(DATABASE_PATH+ "/crazynovel4");
                 files[4] = new File(DATABASE_PATH+ "/crazynovel5");
                 files[5] = new File(DATABASE_PATH+ "/crazynovel6");
                 files[6] = new File(DATABASE_PATH+ "/crazynovel7");
                 files[7] = new File(DATABASE_PATH+ "/crazynovel8");
                 files[8] = new File(DATABASE_PATH+ "/crazynovel9");
                 files[9] = new File(DATABASE_PATH+ "/crazynovel10");
                 files[10] = new File(DATABASE_PATH+ "/crazynovel11");
                 files[11] = new File(DATABASE_PATH+ "/crazynovel12");
                              FileOutputStream fos = new FileOutputStream(databaseFilename);   
                 CreateFromRawDbFiles(files,fos);             }   
                catch (Exception e)   
                {   
                }   
            }  
    //复制文件
      private void copydb(int dbint,String databaseFilename,int FileSize)
      {
      try
      {
              // 获得封装dictionary.db文件的InputStream对象   
      InputStream is = context.getResources().openRawResource(dbint);   
              FileOutputStream fos = new FileOutputStream(databaseFilename);   
              byte[] buffer = new byte[FileSize];   
              int count = 0;   
              // 开始复制dictionary.db文件   
              while ((count = is.read(buffer)) > 0)   
              {   
                  fos.write(buffer, 0, count);   
              }   
              fos.close();   
              is.close();
      }
      catch(Exception e)   
      {}
      }
        
        
      //合并并拷贝数据
      private void CreateFromRawDbFiles(File[] filelist,FileOutputStream Fos)
      {
    try
       {
      for (File file : filelist)
      {
      InputStream inputFile = new FileInputStream(file);
      int TotalLength = 0;
      try 
      {
      TotalLength = inputFile.available();
      } 
      catch (IOException e)
      {
      }

      // Reading and writing the file Method 1 :
      byte[] buffer = new byte[TotalLength];
      int len = 0;
      try
      {
      len = inputFile.read(buffer);
      } 
      catch (IOException e)
      {
      }
      Fos.write(buffer,0,len);
      inputFile.close();
      }
      Fos.close();
     }
      catch(IOException e)
      {}
    }由于拷贝文件和合并文件都是很费时的事情,最好大家用线程来调用上面的代码,并加进度条显示当前进度。具体就写了。希望对大家有帮助。
      

  15.   

    楼主,我也碰到这个问题了,但是我的内存卡上并没有sdcard这个文件夹,怎么办呢?自己新建了也不可以,帮忙解决哈,谢谢!
      

  16.   

    找资料找到这个帖子,我现在的应用就是按这个办法,res\raw中包含db,运行时检测sd卡有没有,没有就释放这个db到sd卡,然后读数据库可是,这还不是我最终的目标,因为这样还存在一个问题,db文件存在sd卡上而不是作为程序的私有数据,也就是说存在被别的程序修改,或者人为修改的可能,破换数据准确性最理想的解法应该是,SQLiteDatabase的create方法支持从已有资源创建私有数据db,可惜找遍都没有资料显示有这样的用法,哎,不知道google程序员怎么想的
      

  17.   

    刚刚接触Android开发,以后多向楼主学习。