无法将 SQLite 数据库从资产文件夹复制到设备内存

Posted

技术标签:

【中文标题】无法将 SQLite 数据库从资产文件夹复制到设备内存【英文标题】:Unable to copy SQLite database from assests folder to device memory 【发布时间】:2011-12-13 09:45:48 【问题描述】:

我无法将 SQLite 数据库从评估文件夹复制到设备内存(在模拟器上尝试)。

我的项目的资产文件夹中有一个数据库,其中有一个包含 1000 条预先存在的行的表。

我打算将现有文件从assets文件夹复制到模拟器的数据库文件夹中。

活动片段

     @Override
public void onCreate(Bundle savedInstanceState) 
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

            //All views(list,textboxes) are declared.
    try 
        dbM = new DbManager(this);
        dbM.checkDataBase();

        try 
            dbM.createDataBase();
         catch (Exception e) 
            throw new Error(" *** ERROR in DB Access *** " + e.getMessage());
        

        dbM.openDB();
        symbolarr = dbM.getSymbol();

        lv.setAdapter(new ArrayAdapter<String>(this,
         android.R.layout.simple_list_item_1, symbolarr));
                 catch (Exception e) 
        throw new Error(" *** ERROR in onCreate *** " + e.getMessage());
    

    finally 
        dbM.close();
    

我的 DbManager 类中的一段代码:

    public boolean checkDataBase() 

    String myPath = DATABASE_PATH + DATABASE_NAME;
    File f = new File(myPath);
    return f.exists();


public void createDataBase() 

    try 
        InputStream myInput = ctx.getAssets().open(DATABASE_NAME);
        OutputStream myOutput = new FileOutputStream(DATABASE_PATH
                + DATABASE_NAME);

        byte[] buffer = new byte[1024];
        int length;
        while ((length = myInput.read(buffer)) > 0) 
            myOutput.write(buffer, 0, length);
        
        myOutput.flush();
        myOutput.close();
        myInput.close();

     catch (FileNotFoundException e) 
        throw new Error("file not found --  " + e.getMessage());
     catch (IOException e) 
        throw new Error("io exception " + e.getMessage());
     catch (Exception e) 
        throw new Error(" exception " + e.getMessage());
    


public DbManager openDB() throws SQLException 
    dbmgr = new DbManager(ctx);
    mDb = dbmgr.getWritableDatabase();
    return this;


public String[] getSymbol() 
    Cursor cur;
    try 
        cur = mDb.rawQuery("select symbol,company_name from Scrip", null);
     catch (SQLiteException e) 
        throw new Error(" *** ERROR in cursor *** " + e.getMessage());
    

    String[] b1 = new String[1326];
    int x = 0;
    if (cur.moveToFirst()) 
        do 
            b1[x] = cur.getString(cur.getColumnIndex("symbol"));
            x++;
         while (cur.moveToNext());
    
    cur.close();
    return b1;

LOGCAT

    FATAL EXCEPTION: main


 java.lang.Error: file not found --  AndroidDB.db
    at com.dbexample.DbManager.createDataBase(DbManager.java:113)
    at com.dbexample.DataAttach.onCreate(DataAttach.java:83)
    at android.app.Activity.performCreate(Activity.java:4465)
    at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1049)
    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1919)
    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1980)
    at android.app.ActivityThread.access$600(ActivityThread.java:122)
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1146)
    at android.os.Handler.dispatchMessage(Handler.java:99)
    at android.os.Looper.loop(Looper.java:137)
    at android.app.ActivityThread.main(ActivityThread.java:4340)
    at java.lang.reflect.Method.invokeNative(Native Method)
    at java.lang.reflect.Method.invoke(Method.java:511)
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:784)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:551)
    at dalvik.system.NativeStart.main(Native Method)

注意

1:更改缓冲区大小无济于事..

2:我的资产文件夹中有一个名为 AndroidDB.db 的文件,大小为 62kb。

3:数据库名称(在我的资产文件夹和我的代码中)是相同的,并且我的数据库中有 android_metadata 表,它位于资产文件夹中..

4:当我不使用 createDataBase() 时,正在创建数据库,但没有复制我想要的表,即脚本。所以当我试图从表中获取数据时,我得到了一个异常no such table Scrip.... 这意味着我需要将 Scrip 表从资产文件夹复制到模拟器内存​​上的数据库。当我尝试使用createDataBase() 做同样的事情时,我得到了 nullPointerException

5.: 当我在 createDatabase() 中尝试以下代码时

AssetManager assetManager = ctx.getAssets();
            String[] files = assetManager.list("Files");

            for (int i = 0; i < files.length; i++) 
                str[i] = "\n=" + " file=" + " :" + i + "=" + " name=" + "> "
                        + files[i];
            
            Log.v("len=", "" + files.length);

那么 files.length 等于 0。这只是意味着它无法检测到资产文件夹中的任何文件。

任何帮助都将成为救命稻草!!!

【问题讨论】:

db文件的大小呢? /data/data/com.dbexample/databases/文件夹中是否有创建文件? 这个大小和asset文件夹里的db文件一样吗? 你可以从here得到它 OMG... 它有效... 感谢一百万吨 这是一个愚蠢的错误。 【参考方案1】:

编辑:用这个替换你的代码,让我知道发生了什么,(这在我的情况下很好用..)

DbManager.java 类:

public class DbManager 
private DatabaseHelper dataHelper;
private SQLiteDatabase  mDb;
Context ctx;
String DATABASE_PATH = "/data/data/com.demo/databases/";
static String DATABASE_NAME="AndroidDB";

private static final int DATABASE_VERSION = 1;
DbManager(Context ctx)

    this.ctx = ctx;
    dataHelper = new DatabaseHelper(ctx);



private static class DatabaseHelper extends SQLiteOpenHelper 

    Context myContext = null;

    public DatabaseHelper(Context context) 
        super(context, DATABASE_NAME, null, DATABASE_VERSION);
        this.myContext = context;
        // TODO Auto-generated constructor stub
    

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

    

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

        Log.w("DBHelper", "Upgrading database from version "
                        + oldVersion + " to " + newVersion
                        + ", which will destroy all old data");

        onCreate(db);

    




   public boolean checkDataBase() 

        String myPath = DATABASE_PATH + DATABASE_NAME;
        File f = new File(myPath);
        return f.exists();
    

    public void createDataBase() 

        openDB();            
        try 
            InputStream myInput = ctx.getAssets().open("AndroidDB.db");
            OutputStream myOutput = new FileOutputStream(DATABASE_PATH
                    + "AndroidDB");

            byte[] buffer = new byte[1024];
            int length;
            while ((length = myInput.read(buffer)) > 0) 
                myOutput.write(buffer, 0, length);
            

            if (mDb.isOpen())
                mDb.close();
            myOutput.flush();
            myOutput.close();
            myInput.close();

         catch (FileNotFoundException e) 
            throw new Error("file not found --  " + e.getMessage());
         catch (IOException e) 
            throw new Error("io exception " + e.getMessage());
         catch (Exception e) 
            throw new Error(" exception " + e.getMessage());
        
    

    public DbManager openDB() throws SQLException 

        mDb = dataHelper.getWritableDatabase();
        return this;
    

    public String[] getSymbol() 
        Cursor cur;
        try 
            cur = mDb.rawQuery("select symbol,company_name from Scrip", null);
         catch (SQLiteException e) 
            throw new Error(" *** ERROR in cursor *** " + e.getMessage());
        

        String[] b1 = new String[1326];
        int x = 0;
        if (cur.moveToFirst()) 
            do 
                b1[x] = cur.getString(cur.getColumnIndex("symbol"));
                x++;
             while (cur.moveToNext());
        
        cur.close();
        return b1;
    

    public void close() 
        try 
            mDb.close();
         catch (Exception e) 
            e.printStackTrace();
        

 


【讨论】:

我已经更新了 DATABASE_PATH 到我的 pkg,但仍然是 fileNotFoundException... OMG... 它有效... 感谢一百万吨 这是一个愚蠢的错误。【参考方案2】:

检查您添加的数据库名称和错误写入的数据库名称是否相同? (AndroidDB.db) 还要确保您的数据库中有 android_metadata 表。 :)

【讨论】:

两个名称都相同,我的数据库中有 android_metadata 表,位于 assets 文件夹中。 你的代码和我的一模一样,我的代码运行良好。可能是 user370305 的尝试解决方案,他很聪明,解决了我的许多答案:P【参考方案3】:

认为您可以从现有数据库中获取路径。那么为什么不让 Android 先创建数据库呢?

在复制您的数据库之前尝试执行“getWritableDb”。然后通过“db.getPath()”获取路径并使用此路径从资产中复制。

这对我有用。

【讨论】:

我主要关心的是 copyDatabase 方法。它给了 fileNotFoundException..

以上是关于无法将 SQLite 数据库从资产文件夹复制到设备内存的主要内容,如果未能解决你的问题,请参考以下文章

将 db 从资产复制到设备数据文件夹时出现 FileNotFoundException

从无根设备中的资产文件夹复制数据库

C#:在 Android 上复制资产

将 SQLite 数据库从 sdcard 导入到 android - 没有资产文件夹

无法将 sqlite 文件从应用程序包复制到文档目录:获取(Cocoa 错误 260)

以编程方式从应用程序的资产文件夹复制数据库文件