从预填充的数据库中读取数据时出错

Posted

技术标签:

【中文标题】从预填充的数据库中读取数据时出错【英文标题】:error reading data from the pre-filled database 【发布时间】:2019-05-05 02:39:50 【问题描述】:

我有一个位于 assets/databases/ 中的数据库。我使用库android-sqlite-asset-helper 试图归档数据库,没有帮助。错误仍然出现

   E/SQLiteAssetHelper: Couldn't open databases/brodsky.db for writing (will try read-only):
    com.readystatesoftware.sqliteasset.SQLiteAssetHelper$SQLiteAssetException: Missing databases/databases/brodsky.db file (or .zip, .gz archive) in assets, or target folder not writable
        at android.content.res.AssetManager.openAsset(Native Method)
        at android.content.res.AssetManager.open(AssetManager.java:336)
        at android.content.res.AssetManager.open(AssetManager.java:310)
        at com.readystatesoftware.sqliteasset.SQLiteAssetHelper.copyDatabaseFromAssets(SQLiteAssetHelper.java:436)
        at com.readystatesoftware.sqliteasset.SQLiteAssetHelper.createOrOpenDatabase(SQLiteAssetHelper.java:400)
        at com.readystatesoftware.sqliteasset.SQLiteAssetHelper.getWritableDatabase(SQLiteAssetHelper.java:176)
        at com.readystatesoftware.sqliteasset.SQLiteAssetHelper.getReadableDatabase(SQLiteAssetHelper.java:254)
        at rodionova.lyubov.brodsky.db.PoemsProvider.query(PoemsProvider.java:40)
        at android.content.ContentProvider.query(ContentProvider.java:1140)
        at android.content.ContentProvider$Transport.query(ContentProvider.java:262)
        at android.content.ContentResolver.query(ContentResolver.java:506)

DbHelper:

    public class PoemsDbHelper extends SQLiteAssetHelper 

    private static String DB_NAME = "databases/brodsky.db";
    private static final int DB_VERSION = 1;

    public PoemsDbHelper(Context context) 
        super(context, DB_NAME, null, DB_VERSION);
    

还有一个 ContentProvider 类,因为它也在日志中的错误中指定

公共类 PoemsProvider 扩展 ContentProvider 私有静态最终 UriMatcher URI_MATCHER = new UriMatcher(UriMatcher.NO_MATCH); 私有静态最终 int POEMS = 1; 私有静态最终 int POEM = 2; 私有静态最终 int FACTS = 3; 私有静态最终 int BIOGRAPHY = 4;

static 
    URI_MATCHER.addURI(PoemsContract.AUTHORITY, "poems", POEMS);
    URI_MATCHER.addURI(PoemsContract.AUTHORITY, "poems/#", POEM);
    URI_MATCHER.addURI(PoemsContract.AUTHORITY, "facts", FACTS);
    URI_MATCHER.addURI(PoemsContract.AUTHORITY, "biography", BIOGRAPHY);


private PoemsDbHelper poemsDbHelper;

@Override
public boolean onCreate() 
    poemsDbHelper = new PoemsDbHelper(getContext());
    return true;


@Nullable
@Override
public Cursor query(@NonNull Uri uri, @Nullable String[] projection, @Nullable String selection,
                    @Nullable String[] selectionArgs, @Nullable String sortOrder) 
    SQLiteDatabase db = poemsDbHelper.getReadableDatabase();
    switch (URI_MATCHER.match(uri)) 
        case POEMS:
            if (TextUtils.isEmpty(sortOrder)) 
                sortOrder = PoemsContract.Poems.COLUMN_ID + " DESC";
            

            return db.query(PoemsContract.Poems.TABLE_NAME,
                    projection,
                    selection,
                    selectionArgs,
                    null,
                    null,
                    sortOrder);

        case POEM:
            String id = uri.getLastPathSegment();
            if (TextUtils.isEmpty(selection)) 
                selection = PoemsContract.Poems._ID + " = ?";
                selectionArgs = new String[]id;
             else 
                selection = selection + " AND " + PoemsContract.Poems._ID + " = ?";

                String[] newSelectionArgs = new String[selectionArgs.length + 1];

                System.arraycopy(selectionArgs, 0, newSelectionArgs, 0, selectionArgs.length);

                newSelectionArgs[newSelectionArgs.length - 1] = id;

                selectionArgs = newSelectionArgs;
            
        case FACTS:
            if (TextUtils.isEmpty(sortOrder)) 
                sortOrder = PoemsContract.Facts.COLUMN_ID + " DESC";
            

            return db.query(PoemsContract.Facts.TABLE_NAME,
                    projection,
                    selection,
                    selectionArgs,
                    null,
                    null,
                    sortOrder);
        case BIOGRAPHY:
            if (TextUtils.isEmpty(sortOrder)) 
                sortOrder = PoemsContract.Biography.COLUMN_ID + " DESC";
            

            return db.query(PoemsContract.Biography.TABLE_NAME,
                    projection,
                    selection,
                    selectionArgs,
                    null,
                    null,
                    sortOrder);

        default:
            return null;
    


【问题讨论】:

【参考方案1】:

而不是private static String DB_NAME = "databases/brodsky.db";

你应该使用private static String DB_NAME = "brodsky.db";

SQliteAssetHelper 在自述文件中包含以下内容:-

像通常的 SQLiteOpenHelper 一样扩展 SQLiteAssetHelper, 为构造函数提供数据库名称和版本号:

public class MyDatabase extends SQLiteAssetHelper 

    private static final String DATABASE_NAME = "northwind.db";
    private static final int DATABASE_VERSION = 1;

    public MyDatabase(Context context) 
      super(context, DATABASE_NAME, null, DATABASE_VERSION);
    

SQLiteAssetHelper 依赖于资产文件和文件夹命名 公约。您的资产文件夹将在您的项目下 root,或者如果您使用默认的 gradle 项目,则在 src/main 下 结构体。至少,您必须提供以下内容:

assets 中的 databases 文件夹 文件名与您提供的数据库名称匹配的数据库文件夹 在代码中(包括文件扩展名,如果有的话)对于上面的例子, 该项目将包含以下内容:

assets/databases/northwind.db

【讨论】:

以上是关于从预填充的数据库中读取数据时出错的主要内容,如果未能解决你的问题,请参考以下文章

在JAVA中读取XML文件并创建数据库

从连接 Firebird 读取数据时出错

从 firebase 读取数据,并在 listview 中填充

从 MySQL 表 1064 读取数据时出错 (42000)

在Android上的蓝牙中从InputStream读取数据时出错

读取 csv 文件并在 python 中返回数据帧时出错