Java 请求索引0,SQLITE DB中出现大小为0的错误

Java 请求索引0,SQLITE DB中出现大小为0的错误,java,android,sqlite,android-cursor,Java,Android,Sqlite,Android Cursor,数据库中有数据(精确地说是两行),每行中都有信息 以下是来自DBADAPTER的代码(重要的不是全部): // Field Names: public static final String KEY_ROWID = "_id"; public static final String KEY_DEVICE = "device"; public static final String KEY_TYPE = "type"; public static final Str

数据库中有数据(精确地说是两行),每行中都有信息

以下是来自DBADAPTER的代码(重要的不是全部):

// Field Names:
    public static final String KEY_ROWID = "_id";
    public static final String KEY_DEVICE = "device";
    public static final String KEY_TYPE = "type";
    public static final String KEY_DEVID = "devid";

    public static final String[] ALL_KEYS = new String[] {KEY_ROWID, KEY_DEVICE, KEY_TYPE, KEY_DEVID};
    public static final String[] DEVID_KEY = new String[] {KEY_DEVID};

    // Column Numbers for each Field Name:
    public static final int COL_ROWID = 0;
    public static final int COL_DEVICE = 1;
    public static final int COL_TYPE = 2;
    public static final int COL_DEVID = 3;

    // DataBase info:
    public static final String DATABASE_NAME = "dbDevices";
    public static final String DATABASE_TABLE = "mainDevices";
    public static final int DATABASE_VERSION = 10; // The version number must be incremented each time a change to DB structure occurs.

    //SQL statement to create database
    private static final String DATABASE_CREATE_SQL = 
            "CREATE TABLE " + DATABASE_TABLE 
            + " (" + KEY_ROWID + " INTEGER PRIMARY KEY AUTOINCREMENT, "
            + KEY_DEVICE + " TEXT NOT NULL, "
            + KEY_TYPE + " TEXT, "
            + KEY_DEVID + " TEXT NOT NULL "
            + ");";

    private final Context context;
    private DatabaseHelper myDBHelper;
    private SQLiteDatabase db;

    // Get a specific row (by devid)
        public String getDevName(String devid) {
            String name;
            String where = KEY_DEVID + " like '%" + devid + "%'";
            Cursor c =  db.query(true, DATABASE_TABLE, ALL_KEYS, 
                            where, null, null, null, null, null);
                c.moveToFirst();
                name = c.getString(COL_DEVICE);
            return name;
        }
下面是调用它的代码:

String incomingMessage = " ";
incomingMessage = in.readLine() + System.getProperty("line.separator");
devName = devDB.getDevName(incomingMessage);
我知道这是在获取信息,因为它会记录:
03-16 15:39:47.072:V/String(18073):5122

每当我运行此命令时,都会出现以下错误:

03-16 15:39:47.122: W/System.err(18073): android.database.CursorIndexOutOfBoundsException: Index 0 requested, with a size of 0
03-16 15:39:47.122: W/System.err(18073):    at android.database.AbstractCursor.checkPosition(AbstractCursor.java:426)
03-16 15:39:47.122: W/System.err(18073):    at android.database.AbstractWindowedCursor.checkPosition(AbstractWindowedCursor.java:136)
03-16 15:39:47.132: W/System.err(18073):    at android.database.AbstractWindowedCursor.getString(AbstractWindowedCursor.java:50)
03-16 15:39:47.132: W/System.err(18073):    at com.ti.cc3x.android.DBAdapter.getDevName(DBAdapter.java:121)
03-16 15:39:47.132: W/System.err(18073):    at com.ti.cc3x.android.broadcastListener$1.run(broadcastListener.java:112)
03-16 15:39:47.132: W/System.err(18073):    at java.lang.Thread.run(Thread.java:841)

我已尝试检查非空游标。我所做的就是什么也不告诉我。我知道有数据,我要求它看我只是不知道为什么它不会显示它。谁能告诉我哪里出了问题?谢谢大家!

您正在使用
SQLiteOpenHelper
?如果是这样,在尝试读取或写入数据库之前,您需要将数据库变量
db
设置为数据库,如下所示:

db = this.getWritableDatabase();
。。。新的
getDevName(…)
方法应该如下所示:

public String getDevName(String devid) {
    db = this.getWritableDatabase();

    String name;
    String where = KEY_DEVID + " like '%" + devid + "%'";
    Cursor c =  db.query(true, DATABASE_TABLE, ALL_KEYS, 
                    where, null, null, null, null, null);
    c.moveToFirst();
    name = c.getString(COL_DEVICE);

    db.close(); // close your db connection when you're done with it

    return name;
}
来自Android开发者文档: 公共SQLiteDatabase getWritableDatabase()- 第一次调用它时,将打开数据库并调用onCreate(SQLiteDatabase)、onUpgrade(SQLiteDatabase、int、int)和/或onOpen(SQLiteDatabase)。 一旦成功打开,数据库将被缓存,因此您可以在每次需要写入数据库时调用此方法。(请确保在不再需要数据库时调用close())错误(如权限错误或磁盘已满)可能会导致此方法失败,但如果问题得到解决,则以后的尝试可能会成功

继续从@bwegs展开关于调用
getWritableDatabase()

尝试使用
selectionArgs
,因为它更干净。检查
moveToFirst()
的返回值,确保关闭光标以避免内存泄漏

 public String getDevName(String devid) {
    db = myDBHelper.getWritableDatabase();  //get db if not done so already, you may have already done this in code not shown

    String name = null;
    String where = KEY_DEVID + " like ?";
    String[] selectionArgs =  new String[] {"%"+ devid + "%" };
    Cursor c =  db.query(true, DATABASE_TABLE, ALL_KEYS, 
                    where, selectionArgs , null, null, null, null);

    //Only use cursor if moveToFirst() succeeds
    //this will make it so that you don't get the CursorIndexOutOfBoundsException
    if (c.moveToFirst()){
        name = c.getString(COL_DEVICE);
    }

    c.close(); //close your cursor to avoid memory leak!

    db.close(); //close here if you call getWritableDatabase() in beginning of this function

    //This will return null if no results from query
    return name;
}

发布logcat时,请将其放在代码块中以便于阅读。任何类型的stacktrace或其他冗长的错误消息通常也是如此。此外,我郑重建议在Android上使用第三方SQLite库,除非您是熟练的DBA和/或有实际理由不使用库。Android的默认实现虽然功能强大,但非常麻烦,并且容易出现开发人员错误。我制作了一个小型的、开源的
DatabaseManager
类,它简化了线程和同步。但是我真的建议使用SugarORM、GreenDao或ActiveAndroid(还有其他的)。对于一个潜在的解决方案,您将
传入.readLine()+“\r\n”
(\r\n是一个行分隔符)到
getDevName
,因此您的查询实际上是针对
的,比如“%line\u that\r\n%”
,因此没有返回任何行,因此索引0不可用。这起作用。我删除了行分隔符并使用了Daniel Nugent提供的代码,它输出了我所需要的!令人惊叹的!非常感谢。这与Jakar关于从incomingMessage变量中删除行分隔符的评论一致(我不记得我为什么首先将其放在那里),非常感谢!!!只是一个想法:通常返回null对于指示错误是有用的,但它也有利于
返回“error”这样以后就不会出现空指针异常,而且如果名称被打印出来,那么这是一种无缝的方式来告诉用户错误。但是,这当然取决于个人偏好(或公司偏好)和情况。我们通常对字符串执行空检查,这是我现在工作的标准约定,但是了解其他透视图是很好的。另外,很好地抓住了线分离器的问题!这一答案正在会议上讨论