将db从资产复制到内部应用程序内存时出现IO异常

时间:2013-09-25 04:31:38

标签: android database sqlite ioexception android-assets

我尝试将资产文件夹中的数据库复制到内部应用程序内存。

db包含两个表。一个表是完全空的,应允许用户将其数据插入表中。 另一个表预装了提供应用程序信息的数据(我需要将预加载的数据库加载到应用程序中的原因) 我应该有两个单独的数据库,因为当我处理预加载的数据库时,数据库填充到应用程序内存中就好了,但出于某种原因,由于这个额外的表,我现在无法这样做。

我输入资产的数据库是否可能已损坏,因为我内部没有安装android-metadata?我的资产文件夹中的数据库仅使用CSV工作表中的数据创建。

在此问题出现之前,我会对我的包名称进行折射,并在清单中进行更改。这可能是问题之一吗?

继承代码

DBHelper.class

@Override
public void onCreate(SQLiteDatabase db)
{
    db.execSQL(DB_CREATE_SQL);
    db.execSQL(DB_CREATE_SQL_FOR_GAME);
}
    public void createDatabase(Context context) throws IOException
{
    Log.d("Create Database","In method");
    // If database does not exist, copy it from the asset
    if (checkDatabase() == false)
    {
        try
        {
            // Copy the database from assets
            copyDatabase(context);
            Log.d("Create Database","Copying");
        }
        catch (IOException mIOException)
        {
            Log.d("Create Database","Failed");
            throw new Error("ErrorCopyingDataBase");
        }
    }
}


public void copyDatabase(Context context) throws IOException
{
    // Open your local db as the input stream
    InputStream myInput = context.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 bytes from the inputfile to the outputfile
    byte[] buffer = new byte[10240];
    int length;
    while ((length = myInput.read(buffer)) > 0)
    {
        myOutput.write(buffer, 0, length);
    }
    // Close the streams
    myOutput.flush();
    myOutput.close();
    myInput.close();
}

public boolean checkDatabase()
{

    String myPath = DB_PATH + DB_NAME;
    File f = new File(myPath);
    return f.exists();
}

每当我运行应用程序时,我实际上都会收到IO异常,因为我实际上是在应用程序启动后填充资产。

logcat的

09-25 16:55:42.878: E/SQLiteDatabase(28815): android.database.sqlite.SQLiteCantOpenDatabaseException: unknown error (code 14): Could not open database
09-25 16:55:42.878: E/SQLiteDatabase(28815):    at android.database.sqlite.SQLiteConnection.nativeOpen(Native Method)
09-25 16:55:42.878: E/SQLiteDatabase(28815):    at android.database.sqlite.SQLiteConnection.open(SQLiteConnection.java:278)
09-25 16:55:42.878: E/SQLiteDatabase(28815):    at android.database.sqlite.SQLiteConnection.open(SQLiteConnection.java:217)
09-25 16:55:42.878: E/SQLiteDatabase(28815):    at android.database.sqlite.SQLiteConnectionPool.openConnectionLocked(SQLiteConnectionPool.java:464)
09-25 16:55:42.878: E/SQLiteDatabase(28815):    at android.database.sqlite.SQLiteConnectionPool.open(SQLiteConnectionPool.java:186)
09-25 16:55:42.878: E/SQLiteDatabase(28815):    at android.database.sqlite.SQLiteConnectionPool.open(SQLiteConnectionPool.java:178)
09-25 16:55:42.878: E/SQLiteDatabase(28815):    at android.database.sqlite.SQLiteDatabase.openInner(SQLiteDatabase.java:804)
09-25 16:55:42.878: E/SQLiteDatabase(28815):    at android.database.sqlite.SQLiteDatabase.open(SQLiteDatabase.java:789)
09-25 16:55:42.878: E/SQLiteDatabase(28815):    at android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:694)
09-25 16:55:42.878: E/SQLiteDatabase(28815):    at android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:669)

我尝试在使用getWritableDatabase()创建db的路径(这意味着它将覆盖任何现有的路径)之后将数据库复制到该文件夹​​中,并且我收到此错误

09-26 11:09:46.370: E/System(2444): Uncaught exception thrown by finalizer
09-26 11:09:46.380: E/System(2444): java.io.IOException: close failed: EIO (I/O error)
09-26 11:09:46.380: E/System(2444):     at libcore.io.IoUtils.close(IoUtils.java:41)
09-26 11:09:46.380: E/System(2444):     at java.io.RandomAccessFile.close(RandomAccessFile.java:166)
09-26 11:09:46.380: E/System(2444):     at java.io.RandomAccessFile.finalize(RandomAccessFile.java:175)
09-26 11:09:46.380: E/System(2444):     at java.lang.Daemons$FinalizerDaemon.doFinalize(Daemons.java:186)
09-26 11:09:46.380: E/System(2444):     at java.lang.Daemons$FinalizerDaemon.run(Daemons.java:169)
09-26 11:09:46.380: E/System(2444):     at java.lang.Thread.run(Thread.java:856)
09-26 11:09:46.380: E/System(2444): Caused by: libcore.io.ErrnoException: close failed: EIO (I/O error)
09-26 11:09:46.380: E/System(2444):     at libcore.io.Posix.close(Native Method)
09-26 11:09:46.380: E/System(2444):     at libcore.io.BlockGuardOs.close(BlockGuardOs.java:75)
09-26 11:09:46.380: E/System(2444):     at libcore.io.IoUtils.close(IoUtils.java:38)
09-26 11:09:46.380: E/System(2444):     ... 5 more

3 个答案:

答案 0 :(得分:1)

它实际上是我编写代码的方式。在我的代码中,我使用getWritableDatabase()来创建/ data / data //数据库的目录。但是,当我运行getWritableDatabase()时,也会创建一个虚拟数据库。

所以基本上不是运行getWritableDatabase(),而是用

创建了目录
public void createDirectory()
    {
        File dbDirectory = new File(DB_PATH);
         if (!dbDirectory.exists())
                dbDirectory.mkdirs();
    }

然后我检查我的/ data / data //数据库目录中是否有数据库,并且不应该有任何数据库。因此,我可以从资产中复制数据库,因为文件夹中没有数据库。

希望这有助于任何有类似问题的人。

答案 1 :(得分:0)

尝试此操作访问数据库之前。

            InputStream input = getResources().getAssets().open("db");
            File f = new File("DB_PATH/databases");
            if (f.mkdirs())
            {
                File ff=new File("DB_PATH/databases");
                FileOutputStream output = new FileOutputStream(ff);
                int data = 0;
                byte[] buffer = new byte[1024];
                while ((data = input.read(buffer)) > 0) {
                    output.write(buffer, 0, data);
                }

                input.close();
                output.close();
                Log.d("File", "File Copied!");
            } else {
                Log.d("File", "AlreadyExists!");
            }
        } catch (IOException e1) {
            // TODO Auto-generated catch block
            e1.printStackTrace();
        }

答案 2 :(得分:0)

试试这希望这可以帮到你

import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;

import java.io.BufferedInputStream;
import java.io.IOException;

public class SmartOpenHelper extends SQLiteOpenHelper {

    private Context context;
    private String DB_SQL;

    SmartOpenHelper(Context context, String dbname, int dbversion, String dbSqlName) throws IOException {
        super(context, dbname, null, dbversion);
        this.context = context;
        this.DB_SQL = dbSqlName;
    }

    @Override
    public void onCreate(SQLiteDatabase db) {
        try {
            BufferedInputStream inStream = new BufferedInputStream(context.getAssets().open(DB_SQL));
            String sql = "";
            int character = -2;
            do {
                character = inStream.read();
                if ((character != -1) && (character != -2))
                    sql += (char) character;
                else
                    break;
            } while (true);
            System.out.println("onCreate DB SQL = " + sql.split("\n"));
            String[] arrSQL = sql.split("\n");

            for (int i = 0; i < arrSQL.length; i++) {
                db.execSQL(arrSQL[i]);
            }

        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {

        try {
            BufferedInputStream inStream = new BufferedInputStream(context.getAssets().open(DB_SQL));
            String sql = "";
            int character = -2;
            do {
                character = inStream.read();
                if ((character != -1) && (character != -2))
                    sql += (char) character;
                else
                    break;
            } while (true);

            System.out.println("onUpgrade DB SQL = " + sql.split("\n"));
            String[] arrSQL = sql.split("\n");
            for (int i = 0; i < arrSQL.length; i++) {
                db.execSQL(arrSQL[i]);
            }

        } catch (IOException e) {
            e.printStackTrace();
        }
    }


    public synchronized void close() {
        super.close();
    }

}

如何使用

SmartOpenHelper openHelper = new SmartOpenHelper(this.context, DATABASE_NAME, DATABASE_VERSION, DATABASE_SQL);
SQLiteDatabase db = openHelper.getWritableDatabase();