2012-08-31 12 views
21

Sto cercando di copiare un database che ho fatto con SQLite Manager, in cui ho fatto:Impossibile leggere riga 0, colonna -1

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

e

INSERT INTO "android_metadata" VALUES ('en_US') 

E ho chiamato tutto le mie chiavi primarie _id. Il mio database viene copiato (nella prima esecuzione ci sono vari messaggi rossi nel logcat); da allora in poi, dà solo un errore quando lo interrogo.

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' 

risposta

42

se si vede

failed to read row 0,column -1 

Significa che stai cercando di leggere da una colonna che non esiste.

Se non è possibile trovare il nome della colonna specificato, Cursor.getColumnIndex() restituisce -1 e, quindi, non è valido.

ci sono due ragioni per questo:

  1. La colonna non esiste.
  2. Il nome della colonna non è corretto. (quindi non esiste).

Nota: il nome della colonna è maiuscole e minuscole quando si utilizza getColumnIndex()


nello scenario:

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

Verificare che la variabile CNAME sia stato digitato correttamente, e che esiste una colonna con questo nome

String CNAME=" ques" 

caso che conduce lo spazio vuoto supplementare essere lì per esempio ..

+0

sì funziona ora, ma dovrei preoccuparmi in quanto dà messaggi di errore nel logcat alla prima esecuzione. – dreamer1989

+2

@ dreamer1989 Si dovrebbe preoccupare a seconda del contenuto dei messaggi di errore nel logcat. Ad ogni modo, chiedendo se i messaggi di errore siano preoccupanti o non facciano un'ottima _ seconda domanda_. Non fare questa domanda fare il doppio dovere. –

1

Prima di iniziare a leggere i valori consecutivi utilizzando c.moveToNext(), impostare il cursore alla posizione iniziale, che è l'inizio del database.

c.moveToFirst()

e poi iniziare a forma di leggerlo.

Potrebbe risolvere il tuo problema.

+3

Non sono d'accordo. Non è richiesto l'uso di 'moveToFirst()' prima di 'moveToNext()'. Se hai un nuovo cursore che si trova nell'indice -1, 'moveToNext()' sposterà l'indice a 0 e restituirà true (se c'è almeno una riga). – Sam

+0

@Sam: Sì signore, sono totalmente d'accordo con te! Ma non c'era altra ragione per cui potessi trovare nel suo codice che avrebbe portato il cursore in posizione -1 e quindi ha espresso il mio punto di vista. La tua logica è corretta, ma allora perché l'errore ** solo ** durante la prima esecuzione? È stato il commento sugli errori nella prima esecuzione che mi ha fatto pensare a questo. Notare anche l'uso della parola ** "potrebbe" ** nella mia risposta, poiché non sono un master in SQLite e cursori. :) – Swayam

+0

Capisco la tua logica, ma osservo più da vicino l'errore: 'Impossibile leggere la riga 0, colonna -1'. L'indice della colonna è '-1' non l'indice di riga. – Sam

0

L'errore era l'utilizzo di dieresi ü, ö, ä nei nomi delle colonne del database.

Sebbene sia possibile ottenere il contenuto passando con il metodo cursor.movetonext() così spesso finché non si è passati al numero giusto, è stato molto fastidioso e ha richiesto un sacco di codice.

Immagino che questo dovrebbe risolvere i problemi per la maggior parte di voi. Immagino che qualsiasi cosa tranne ASCII sia sbagliata - spazi, punti, svantaggi ecc., Non possono essere usati neanche.

Si può creare con successo un database e si può vedere con gli strumenti sqlite esterni, ma Android farà sempre il nag.

0

Un altro scenario in cui questo può accadere:
vengono eliminate righe dal cursore mentre il cursore è ancora in uso.

per esempio pseudo-Coden dove potrebbe accadere:

while(cursor.moveToNext()){ 

    readCursor(cursor); 

    deleteRowFromCursor(cursor); 

} 

Soluzione:

lista Torrione di righe che si desidera eliminare; compilare una istruzione sql batch delete; Esegui il movimento della parte esterna del ciclo while (quando hai finito di usare il cursore più o dopo averlo chiuso).

while(cursor.moveToNext()){ 

    readCursor(cursor); 

    queueRowForDelete(cursor); 

} 

deleteQueuedRows(queuedRowsList); 
Problemi correlati