Android 未能读取第 0 行,第 -1 列
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/12222141/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
failed to read row 0,column -1
提问by dreamer1989
I am trying to copy a database that I made with SQLite manager, in which I did:
我正在尝试复制我使用 SQLite 管理器创建的数据库,我在其中执行了以下操作:
CREATE TABLE "android_metadata" ("locale" TEXT DEFAULT 'en_US')
and
和
INSERT INTO "android_metadata" VALUES ('en_US')
And I named all my primary keys _id
. My database gets copied(in the first run there are various red messages in the logcat); thereafter, it only gives an error when I query it.
我命名了我所有的主键_id
。我的数据库被复制(在第一次运行时,logcat 中有各种红色消息);此后,它只会在我查询时出现错误。
MainActivity
主要活动
public class MainActivity extends Activity {
String CNAME=" ques",TABLE_NAME=" JAVAQ";
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Setupdb dbobj=new Setupdb(this);
try {
//dbobj.close();
dbobj.createDataBase();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
dbobj.openDataBase();
dbobj.close();
try{
SQLiteDatabase sqdb=dbobj.getReadableDatabase();
Cursor c = sqdb.query(TABLE_NAME,
new String[] { CNAME },
null, null, null, null, null);
while (c.moveToNext()) {
String name =
c.getString(c.getColumnIndex(CNAME));
Log.i("LOG_TAG", " HAS NAME " + name);
}}
catch(Exception e){
Log.e("err", e.toString());
}
}}
Setupdb
设置数据库
public class Setupdb extends SQLiteOpenHelper {
private static String DB_PATH = "";
private static final String DB_NAME = "camprep.sqlite";
private SQLiteDatabase myDataBase;
private final Context myContext;
private static Setupdb mDBConnection;
public Setupdb(Context context) {
super(context, DB_NAME, null, 3);
this.myContext=context;
DB_PATH="/data/data/"
+ context.getApplicationContext().getPackageName()
+ "/databases/";
Log.e(DB_NAME, DB_PATH);
}
public static synchronized Setupdb getDBAdapterInstance(Context context) {
if (mDBConnection == null) {
mDBConnection = new Setupdb(context);
}
return mDBConnection;
}
public void createDataBase() throws IOException {
boolean dbExist = checkDataBase();
if (dbExist) {
Log.e("db","exist");
// do nothing - database already exist
} else {
// By calling following method
// 1) an empty database will be created into the default system path of your application
// 2) than we overwrite that database with our database.
this.getReadableDatabase();
try {
Log.e("calling", "copy");
copyDataBase();
} catch (IOException e) {
throw new Error("Error copying database");
}
}
}
private boolean checkDataBase() {
SQLiteDatabase checkDB = null;
try {
String myPath = DB_PATH + DB_NAME;
checkDB = SQLiteDatabase.openDatabase(myPath, null,
SQLiteDatabase.OPEN_READONLY);
} catch (SQLiteException e) {
// database does't exist yet.
}
if (checkDB != null) {
checkDB.close();
}
return checkDB != null ? true : false;
}
private void copyDataBase() throws IOException {
// Open your local db as the input stream
InputStream myInput = myContext.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[1024];
int length;
while ((length = myInput.read(buffer)) > 0) {
myOutput.write(buffer, 0, length);
}
// Close the streams
myOutput.flush();
myOutput.close();
myInput.close();
}
public void openDataBase() throws SQLException {
String myPath = DB_PATH + DB_NAME;
myDataBase = SQLiteDatabase.openDatabase(myPath, null, SQLiteDatabase.OPEN_READWRITE);
}
public synchronized void close() {
if (myDataBase != null)
myDataBase.close();
super.close();
}
@Override
public void onCreate(SQLiteDatabase db) {
// TODO Auto-generated method stub
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
}
}
Stacktrace
堆栈跟踪
08-31 20:17:05.320: I/dalvikvm(9457): threadid=3: reacting to signal 3
08-31 20:17:05.370: I/dalvikvm(9457): Wrote stack traces to '/data/anr/traces.txt'
08-31 20:17:05.451: E/camprep.sqlite(9457): /data/data/com.example.mydataexplosion/databases/
08-31 20:17:05.490: E/db(9457): exist
08-31 20:17:05.521: E/CursorWindow(9457): Failed to read row 0, column -1 from a CursorWindow which has 11 rows, 1 columns.
08-31 20:17:05.521: E/err(9457): java.lang.IllegalStateException: Couldn't read row 0, col -1 from CursorWindow. Make sure the Cursor is initialized correctly before accessing data from it.
08-31 20:17:05.650: D/gralloc_goldfish(9457): Emulator without GPU emulation detected.
08-31 20:17:05.650: I/dalvikvm(9457): threadid=3: reacting to signal 3
08-31 20:17:05.670: I/dalvikvm(9457): Wrote stack traces to '/data/anr/traces.txt'
回答by Doomsknight
if you see
如果你看到
failed to read row 0,column -1
It means you are trying to read from a column which doesn't exist.
这意味着您正在尝试从不存在的列中读取数据。
If it cannot find the column name that you specify, Cursor.getColumnIndex()
returns -1
and hence, is invalid.
如果它找不到您指定的列名,则Cursor.getColumnIndex()
返回-1
并因此无效。
There are two reasons for this:
有两个原因:
- The column does not exist.
- The name of the column is incorrect.(so does not exist).
- 该列不存在。
- 列的名称不正确。(所以不存在)。
Note: the name of the column is CASE SENSITIVEwhen using getColumnIndex()
注意:使用时列名是CASE SENSITIVEgetColumnIndex()
In your scenario:
在你的场景中:
c.getString(c.getColumnIndex(CNAME));
Check that the CNAME variable is spelt correctly, and that a column of that name exists.
检查 CNAME 变量是否拼写正确,以及该名称的列是否存在。
String CNAME=" ques"
Should that extra leading white space be there for example..
例如,是否应该有额外的领先空白。
回答by Swayam
Before you start reading the consecutive values by using c.moveToNext()
, set the cursor to the initial position, that is the beginning of your database.
在使用 开始读取连续值之前 c.moveToNext()
,请将光标设置到初始位置,即数据库的开头。
c.moveToFirst()
c.moveToFirst()
and then start reading form it.
然后开始阅读它。
Might solve your problem.
可能会解决你的问题。
回答by Tower Jimmy
The mistake was using umlauts ü,?,? in the database column names.
错误是使用变音 ü,?,? 在数据库列名中。
Although you can get the content by switching with the method cursor.movetonext()
so often until you moved to the right number, it was very annoying and requested a bunch of code.
虽然你可以通过cursor.movetonext()
频繁切换方法来获取内容,直到你移动到正确的数字,这很烦人,并要求一堆代码。
I guess this should solve the problems for most of you. I guess anything but ASCII is wrong -- spaces, dots, minuses etc., cannot be used either.
我想这应该可以解决大多数人的问题。我想除了 ASCII 之外的任何东西都是错误的——空格、点、减号等也不能使用。
You may successfully create a database and you may can see with external sqlite tools but android will always nag.
您可能会成功创建一个数据库,您可能会使用外部 sqlite 工具查看,但 android 总是会唠叨。
回答by dsharew
Another Scenario when this can happen:
You are deleting rows from the cursor while the cursor is still in use.
可能发生这种情况的另一种情况:
您正在从游标中删除行,而游标仍在使用中。
E.g pseudo-coden where it could happen:
例如,它可能发生的伪代码:
while(cursor.moveToNext()){
readCursor(cursor);
deleteRowFromCursor(cursor);
}
Solution:
解决方案:
Keep list of rows you want to delete; build a batch delete sql statement; execute the statment out side of the while loop ( when you are done with using the cursor anymore or after you close it).
保留要删除的行列表;构建批量删除sql语句;在 while 循环之外执行语句(当您不再使用游标时或在您关闭游标后)。
while(cursor.moveToNext()){
readCursor(cursor);
queueRowForDelete(cursor);
}
deleteQueuedRows(queuedRowsList);
回答by Med Mahdi Maarouf
You may need to re-initialize your SQLite database, in order of my experience, I always use ORMLite for Android and I call OnCreate function from my DataBase manager, it is like :
您可能需要重新初始化您的 SQLite 数据库,根据我的经验,我总是使用 ORMLite for Android 并从我的数据库管理器调用 OnCreate 函数,就像:
databaseHelper.onCreate(databaseHelper.getWritableDatabase(),databaseHelper.getConnectionSource());
and I got fixed this error.
我修复了这个错误。
for information, I use an android emulator, not a real device for debugging, I think the differences between both of them can influence on your database storing.
作为参考,我使用的是 android 模拟器,而不是真正的调试设备,我认为它们之间的差异会影响您的数据库存储。