Android不关注文件更改?

时间:2012-06-04 19:30:59

标签: android

我遇到了一个非常令人沮丧的错误。

我有一个java类,它从文件中读取数据,然后将其输入数据库。

 package edu.uci.ics.android;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

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

public class DbAdapter extends SQLiteOpenHelper{

    private static final String DATABASE_NAME = "mydb";
    private static final int DATABASE_VERSION = 1;
    private static final String TABLE_NAME = "fruits";
    private static final String FRUIT_ID = "_id";
    private static final String FRUIT_NAME = "name";
    private static final String FILE_NAME = "fruits.txt";
    private static final String CREATE_TABLE = "CREATE TABLE "+ TABLE_NAME + "("+FRUIT_ID+" integer primary key autoincrement, "+FRUIT_NAME+" text not null);";
    private SQLiteDatabase mDb;
    private Context mContext;

    public DbAdapter(Context ctx){
        super(ctx, DATABASE_NAME, null, DATABASE_VERSION);
        mContext = ctx;
        this.mDb = getWritableDatabase();
    }
    @Override
    public void onCreate(SQLiteDatabase db) {
        db.execSQL(CREATE_TABLE);
        // populate database
        try {
            BufferedReader in = new BufferedReader(new InputStreamReader(mContext.getAssets().open(FILE_NAME)));
            String line;

            while((line=in.readLine())!=null) {
                ContentValues values = new ContentValues();
                values.put(FRUIT_NAME, line);
                db.insert(TABLE_NAME, null, values);
            }
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        db.execSQL("DROP TABLE IF EXISTS "+TABLE_NAME);
        onCreate(db);   
    }

    public Cursor fetchAll() {
        return mDb.query(TABLE_NAME, new String[] {FRUIT_NAME}, null, null, null, null, null);
    }

}

编辑:

更清楚的是,这是失败的:

当我更改数据库名称变量,表名变量时,程序强制关闭,表明出现了问题。为什么我不能更改我创建的表的名称?

当我在fruits.txt文件中进行更改时,我在运行时看不到任何反映这些更改的内容。为什么会这样?

2 个答案:

答案 0 :(得分:3)

只有当数据库不存在时才会自动调用

SQLiteOpenHelper.onCreate(),这只会发生一次。之后,数据库文件存在于设备的内部存储器中,因此它只是加载它拥有的版本。

如果要在更改外部文件时创建新数据库,则需要删除当前数据库文件(手动过程)或更改创建帮助程序的当前数据库版本。当Android看到创建的版本SQLiteOpenHelper与内部存储中的当前文件不同时,它将调用onUpgrade()以允许修改现有数据库以匹配新的“版本”。

编辑:

为了澄清,在创建数据库时,会在设备的内部存储上创建(并保留)db文件,与应用程序的资产分开。当您重新运行应用程序时,持久性数据存储不会清除(或者它不再“持久化”),以便上次运行应用程序时的数据库文件仍然存在...具有从何时开始的所有设置它被创造了。

当您对此类中的变量进行更改时,它不会以某种方式神奇地修改设备上已存在的数据库文件,因此现在您正在查找不存在的表和数据库(可能是您崩溃的地方)来自)。

如果您只是需要清除数据库以便它反映您在开发过程中所做的更改,只需在设备上手动清除数据库,然后进入设置 - >管理应用程序 - > {Application Name} - >清除数据。这会删除持久文件,以便下次启动时可以由应用程序重新创建它们。

但是,如果您需要以某种方式将应用程序自动识别您对/ assets中的文件所做的更改并修改或重新创建数据库,那么请查看我以前的建议使用SQLiteOpenHelper

中内置的升级机制

HTH

答案 1 :(得分:0)

当您在代码中更改数据库名称或表名称时,它们不再反映设备上数据库中的名称,因此您可以关闭力。在开发过程中,最简单的方法是卸载您的应用程序,然后在您进行类似的不兼容更改时重新安装。将数据库架构从一个已发布的版本更改为另一个版本时,需要增加数据库版本号并在onUpgrade()中执行正确的操作。

例如,现在,你有

public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
    db.execSQL("DROP TABLE IF EXISTS "+TABLE_NAME);
    onCreate(db);   
}

因此,当您更改代码中的表名称,将“fruits”更改为“veggies”时,onUpgrade()会运行,但表veggies不存在,因此不会删除,然后你在现有数据库之上调用onCreate(db)一个冲突的shchema。因此,您需要检查oldVeresionnewVersion并执行更多类似

的操作
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
    if (newVersion == 2 && oldVersion == 1) {
        db.execSQL("DROP TABLE IF EXISTS" + TABLE_NAME_V1);
        db.execSQL("CREATE TABLE "+ TABLE_NAME ...);
    }
}

如果您尝试更改设备上的fruits.txt,则无法使用。这就是Android的设计方式:您的资产永远不会改变,它们是您APK的只读部分。如果您希望能够更改它,则需要将fruit.txt文件写入SD卡。