2012-08-31 21 views
21

Próbuję skopiować bazę danych, że zrobiłem z menedżerem SQLite, w którym robiłam:udało się odczytać wiersz 0, kolumna -1

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

i

INSERT INTO "android_metadata" VALUES ('en_US') 

I nazwałem wszystko moje główne klucze _id. Moja baza danych zostanie skopiowana (w pierwszym uruchomieniu są różne czerwone wiadomości w logcat); następnie, tylko daje błąd, gdy go zapytanie.

główną działalność

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' 

Odpowiedz

42

jeśli widzisz

failed to read row 0,column -1 

Oznacza to, że próbujesz odczytać z kolumny, która nie istnieje.

Jeśli nie można znaleźć podanej nazwy kolumny, Cursor.getColumnIndex() zwraca -1, a tym samym jest nieprawidłowy.

Istnieją dwa powody:

  1. Kolumna nie istnieje.
  2. Nazwa kolumny jest niepoprawna. (tak nie istnieje).

Uwaga: nazwa kolumny jest wielkość liter podczas korzystania getColumnIndex()


W swoim scenariuszu:

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

Sprawdź, czy zmienna CNAME jest wpisany poprawnie, a które kolumna o tej nazwie istnieje.

String CNAME=" ques" 

Jeżeli ten dodatkowy wiodącym spacje tam być np ..

+0

Tak, teraz działa, ale powinienem się martwić, ponieważ daje komunikaty o błędach w logcat przy pierwszym uruchomieniu. – dreamer1989

+2

@ dreamer1989 Powinieneś się martwić w zależności od zawartości komunikatów o błędach w kodzie logowania. Tak czy inaczej, zadając pytanie, czy komunikaty o błędach są niepokojące, czy nie, stanowią doskonałe drugie pytanie. Nie zadawaj tej kwestii podwójnego obowiązku. –

1

Zanim zaczniesz czytać kolejnych wartości za pomocą c.moveToNext(), ustaw kursor do pozycji wyjściowej, że to początek bazy danych.

c.moveToFirst()

a następnie rozpocząć czytanie formularz go.

Może rozwiązać Twój problem.

+3

Nie zgadzam się. Nie ma wymogu używania 'moveToFirst()' przed 'moveToNext()'. Jeśli masz nowy kursor o indeksie -1, 'moveToNext()' przesunie indeks do 0 i zwróci true (jeśli jest co najmniej jeden wiersz). – Sam

+0

@Sam: Tak, sir, całkowicie się z tobą zgadzam! Ale nie było innego powodu, dla którego mógłbym znaleźć w swoim kodzie, który zmieniłby kursor na pozycję -1, a tym samym wyraził moją opinię na ten temat. Twoja logika jest poprawna, ale dlaczego błąd ** występuje tylko ** podczas pierwszego uruchomienia? To była uwaga na temat błędów popełnionych przy pierwszym uruchomieniu, co spowodowało, że pomyślałem o tym. Zwróć też uwagę na użycie słowa ** "może" ** w mojej odpowiedzi, ponieważ nie jestem mistrzem w SQLite i kursorach. :) – Swayam

+0

Rozumiem twoją logikę, ale przyjrzyj się bliżej błędowi: 'Nie udało się odczytać wiersza 0, kolumny -1'. Indeks kolumny to "-1", a nie indeks wiersza. – Sam

0

Błąd polegał na użyciu umlautów ü, ö, ä w nazwach kolumn bazy danych.

Mimo że można uzyskać zawartość, przełączając się z metodą cursor.movetonext() tak często, aż przeniósł się na odpowiedni numer, było bardzo denerwujące i poprosił o kilka kodu.

To powinno rozwiązać problemy większości z was. Zgaduję, że wszystko poza ASCII jest złe - spacje, kropki, minusy itp. Też nie mogą być użyte.

Możesz pomyślnie utworzyć bazę danych i możesz zobaczyć za pomocą zewnętrznych narzędzi sqlite, ale android zawsze będzie grzebał.

0

Kolejny scenariusz, gdy może się to zdarzyć: Usuwasz wiersze z kursora, gdy kursor jest nadal używany.

Np pseudo Przedmiot gdzie może się zdarzyć:

while(cursor.moveToNext()){ 

    readCursor(cursor); 

    deleteRowFromCursor(cursor); 

} 

Rozwiązanie:

lista Przechowywać wierszy, które chcesz usunąć; zbuduj wsadowe polecenie delete sql; wykonaj instrukcję poza stroną pętli while (po zakończeniu używania kursora lub po jego zamknięciu).

while(cursor.moveToNext()){ 

    readCursor(cursor); 

    queueRowForDelete(cursor); 

} 

deleteQueuedRows(queuedRowsList); 
Powiązane problemy