从assets文件夹复制SQLite数据库的问题

3

有人能够指导我吗?我可以在/data/data/mypacket/databases目录创建一个空的数据库,但是我无法从资产文件夹中复制我的数据库。有什么建议吗?感谢您的帮助。

代码:

import java.io.File; 
import java.io.FileOutputStream; 
import java.io.IOException; 
import java.io.InputStream; 
import java.io.OutputStream; 

import android.content.Context; 
import android.database.SQLException; 
import android.database.sqlite.SQLiteDatabase; 
import android.database.sqlite.SQLiteOpenHelper; 
import android.util.Log; 

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 ="MyDatabase";// Database name 
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/"; 
    this.mContext = context; 
}    

public void createDataBase() throws IOException 
{ 
    //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)  
        { 
            throw new Error("ErrorCopyingDataBase"); 
        } 
    } 
} 
    //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 
    { 
        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(); 
    } 

    //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

    } 

} 

日志记录:

 09-03 02:22:32.459: E/AndroidRuntime(19099): FATAL EXCEPTION: main
    09-03 02:22:32.459: E/AndroidRuntime(19099): java.lang.IllegalStateException: Could not execute method of the activity
    09-03 02:22:32.459: E/AndroidRuntime(19099):    at android.view.View$1.onClick(View.java:3597)
    09-03 02:22:32.459: E/AndroidRuntime(19099):    at android.view.View.performClick(View.java:4202)
    09-03 02:22:32.459: E/AndroidRuntime(19099):    at android.view.View$PerformClick.run(View.java:17340)
    09-03 02:22:32.459: E/AndroidRuntime(19099):    at android.os.Handler.handleCallback(Handler.java:725)
    09-03 02:22:32.459: E/AndroidRuntime(19099):    at android.os.Handler.dispatchMessage(Handler.java:92)
    09-03 02:22:32.459: E/AndroidRuntime(19099):    at android.os.Looper.loop(Looper.java:137)
    09-03 02:22:32.459: E/AndroidRuntime(19099):    at android.app.ActivityThread.main(ActivityThread.java:5039)
    09-03 02:22:32.459: E/AndroidRuntime(19099):    at java.lang.reflect.Method.invokeNative(Native Method)
    09-03 02:22:32.459: E/AndroidRuntime(19099):    at java.lang.reflect.Method.invoke(Method.java:511)
    09-03 02:22:32.459: E/AndroidRuntime(19099):    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:793)
    09-03 02:22:32.459: E/AndroidRuntime(19099):    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:560)
    09-03 02:22:32.459: E/AndroidRuntime(19099):    at dalvik.system.NativeStart.main(Native Method)
    09-03 02:22:32.459: E/AndroidRuntime(19099): Caused by: java.lang.reflect.InvocationTargetException
    09-03 02:22:32.459: E/AndroidRuntime(19099):    at java.lang.reflect.Method.invokeNative(Native Method)
    09-03 02:22:32.459: E/AndroidRuntime(19099):    at java.lang.reflect.Method.invoke(Method.java:511)
    09-03 02:22:32.459: E/AndroidRuntime(19099):    at android.view.View$1.onClick(View.java:3592)
    09-03 02:22:32.459: E/AndroidRuntime(19099):    ... 11 more
    09-03 02:22:32.459: E/AndroidRuntime(19099): Caused by: java.lang.Error: Error copying database
    09-03 02:22:32.459: E/AndroidRuntime(19099):    at com.petermihaylov.scjajavaexamquestions.DataBaseHelper.createDataBase(DataBaseHelper.java:56)
    09-03 02:22:32.459: E/AndroidRuntime(19099):    at com.petermihaylov.scjajavaexamquestions.TestAdapter.createDatabase(TestAdapter.java:25)
    09-03 02:22:32.459: E/AndroidRuntime(19099):    at com.petermihaylov.scjajavaexamquestions.TrueAndFalse.testasd(TrueAndFalse.java:25)
    09-03 02:22:32.459: E/AndroidRuntime(19099):    ... 14 more

考虑将mLength设置为long类型,仅因为需要获取长整型值; - Sunil Kumar
3个回答

2
一些提示:
  • 检查文件`DB_NAME`是否存在于应用程序的“assets”文件夹中(而不是“raw”文件夹中)。
  • 如果资产文件扩展名为“.gz”,则将删除扩展名。
  • 资产文件的大小不应超过1MB。如果情况如此,请尝试压缩并解压缩到数据库文件夹。
  • 在复制文件之前检查路径`outFileName`是否存在(即`new File(outFileName).getParentFile().mkdirs();`
  • 根据API版本正确构建`DB_PATH`。
此答案所述:
if(android.os.Build.VERSION.SDK_INT >= 4.2){
    DB_PATH = context.getApplicationInfo().dataDir + "/databases/";         
}
else
{
    DB_PATH = "/data/data/" + context.getPackageName() + "/databases/";
}

此外,不要忘记创建 android_metadata 表格,如此答案所解释的那样。

我正在使用Android Studio创建我的项目,但没有Assets文件夹。也许我需要查看一下并确保它在正确的位置/名称上。 没有文件扩展名,DB小于1MB,DB路径已构建并将一个空的DB放置在正确的位置。唯一剩下的就是确保我的资产文件夹没有任何问题。 - FC_Inter_Fan

1
我的问题的解决方案是这样的:
由于Android Studio使用新的基于Gradle的构建系统,您应该将assets/放在源集示例myproject/src/main/assets/中。
我创建了自己的assets文件夹,并将其放在Eclipse通常放置它的位置...这给我带来了所有这些问题。

你必须已经提到了你正在使用“Android Studio”。既然你在这里提到的方法解决了你的问题,所以最好接受它作为答案。 - Krrishnaaaa
我只能在发布24小时后接受自己的答案。我没有意识到Android Studio会导致问题,认为我的代码有错误。 - FC_Inter_Fan

0

以下是一些代码,用于将资产数据库文件夹中的内容复制到外部存储文件夹中。文件需要位于assets\databases文件夹下。

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import android.app.Activity;
import android.media.MediaScannerConnection;
import android.os.Bundle;
import android.os.Environment;
import android.view.View;

public class Options extends Activity {

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        this.setContentView(R.layout.options);
    }            

    public void backupDatabase(View v) throws IOException {                 
        if (Environment.getExternalStorageState() != null)
        {
            File dir = new File(Environment.getExternalStorageDirectory().getAbsolutePath() + "/MyApp");
            if (dir.exists()) {
                //dir.delete();
            }
            else {
                dir.mkdir();
            }

            String fromPath = "";
            if(android.os.Build.VERSION.SDK_INT >= 4.2){
                fromPath = getApplicationInfo().dataDir + "/databases/" + "wl.db";         
            }
            else
            {
                fromPath = "/data/data/" + getPackageName() + "/databases/" + "wl.db";
            }

            String toPath = dir.getAbsolutePath() + "/wl.db";

            fileCopy(new File(fromPath), new File(toPath));

            //This is to refresh the folders in Windows USB conn.
            MediaScannerConnection.scanFile(this, new String[] { Environment.getExternalStorageDirectory().getAbsolutePath() + "/MyApp" }, null, null);         
            MediaScannerConnection.scanFile(this, new String[] { toPath }, null, null);         
        }                   
    }

    public void fileCopy(File src, File dst) throws IOException {
        InputStream in = new FileInputStream(src);
        OutputStream out = new FileOutputStream(dst);

        byte[] buf = new byte[1024];
        int len;
        while ((len = in.read(buf)) > 0) {
            out.write(buf, 0, len);
        }
        in.close();
        out.close();
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接