2012-08-31 21 views
21

que estoy tratando de copiar una base de datos que hice con gestor de SQLite, en la que lo hice:No se pudo leer la fila 0, columna -1

CREATE TABLE "android_metadata" ("locale" TEXT DEFAULT 'en_US') 

y

INSERT INTO "android_metadata" VALUES ('en_US') 

Y puse el nombre de todos mis claves principales _id. Mi base de datos se copia (en la primera ejecución hay varios mensajes rojos en el logcat); a partir de entonces, solo da un error cuando lo consulto.

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' 

Respuesta

42

ver si

failed to read row 0,column -1 

Significa que está tratando de leer de una columna que no existe.

Si no puede encontrar el nombre de columna que especifique, Cursor.getColumnIndex() devuelve -1 y, por lo tanto, no es válido.

Hay dos razones para esto:

  1. La columna no existe.
  2. El nombre de la columna es incorrecto. (entonces no existe).

Nota: el nombre de la columna es mayúsculas y minúsculas cuando se utiliza getColumnIndex()


En su escenario:

c.getString(c.getColumnIndex(CNAME)); 

Comprobar que la variable CNAME está escrito correctamente, y que una columna de ese nombre existe.

String CNAME=" ques" 

En caso de que el espacio en blanco al principio extra de estar allí, por ejemplo ..

+0

sí funciona ahora, pero debería preocuparme ya que da mensajes de error en el logcat en la primera ejecución. – dreamer1989

+2

@ dreamer1989 Debe preocuparse dependiendo del contenido de los mensajes de error en el logcat. De cualquier forma, pregunta si los mensajes de error son preocupantes o no constituyen una excelente "segunda pregunta". No hagas que esta pregunta sea doblemente útil. –

1

Antes de comenzar la lectura de los valores consecutivos mediante el uso de c.moveToNext(), coloque el cursor a la posición inicial, que es el comienzo de su base de datos.

c.moveToFirst()

y luego comenzar la forma de leerlo.

Podría resolver su problema.

+3

No estoy de acuerdo. No es necesario utilizar 'moveToFirst()' antes de 'moveToNext()'. Si tiene un cursor nuevo que está en el índice -1, 'moveToNext()' moverá el índice a 0 y devolverá verdadero (si hay al menos una fila). – Sam

+0

@Sam: ¡Sí, señor, estoy totalmente de acuerdo con usted! Pero no había otra razón que pudiera encontrar en su código que hubiera llevado el cursor a la posición -1 y, por lo tanto, le di mi punto de vista. Su lógica es correcta, pero ¿por qué el error ** solo ** durante la primera ejecución? Fue el comentario sobre los errores en la primera carrera lo que me hizo pensar en esto. También note el uso de la palabra ** "might" ** en mi respuesta, ya que no soy maestro en SQLite y cursores. :) – Swayam

+0

Entiendo su lógica, pero eche un vistazo más de cerca al error: 'Error al leer la fila 0, columna -1'. El índice de la columna es '-1', no el índice de la fila. – Sam

0

El error fue usar umlauts ü, ö, ä en los nombres de las columnas de la base de datos.

Aunque puede obtener el contenido cambiando con el método cursor.movetonext() tantas veces hasta que se movió al número correcto, fue muy molesto y solicitó un montón de código.

Supongo que esto solucionará los problemas para la mayoría de ustedes. Supongo que todo lo que no sea ASCII es incorrecto: espacios, puntos, menos, etc., tampoco se pueden usar.

Puede crear con éxito una base de datos y puede verla con herramientas externas de sqlite, pero Android siempre molestará.

0

otro escenario cuando esto puede suceder:
Se dispone a eliminar filas desde el cursor mientras el cursor está todavía en uso.

por ejemplo pseudo-coden en el que podría suceder:

while(cursor.moveToNext()){ 

    readCursor(cursor); 

    deleteRowFromCursor(cursor); 

} 

Solución:

Lista Sigue de filas que desea eliminar; construir un lote eliminar declaración sql; ejecuta la declaración fuera del bucle while (cuando hayas terminado de usar el cursor o después de cerrarlo).

while(cursor.moveToNext()){ 

    readCursor(cursor); 

    queueRowForDelete(cursor); 

} 

deleteQueuedRows(queuedRowsList); 
Cuestiones relacionadas