2012-08-31 52 views
21

我試圖複製我的SQLite的經理做了一個數據庫,其中我做:無法讀取行0,列-1

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

INSERT INTO "android_metadata" VALUES ('en_US') 

我叫所有我的主鍵_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) { 


} 

} 

堆棧跟蹤

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' 

回答

42

如果你看到

failed to read row 0,column -1 

這意味着您正試圖從不存在的列中讀取數據。

如果找不到指定的列名稱,則Cursor.getColumnIndex()返回-1,因此無效。

有兩個原因:

  1. 列不存在。
  2. 該列的名稱不正確。(所以不存在)。

注:列的名稱使用getColumnIndex()


時,在你的情況是大小寫敏感

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

檢查CNAME變量的拼寫是否正確,以及該名稱的列存在。

String CNAME=" ques" 

應該額外的前導空格在那裏例如..

+0

是的,它現在可以工作,但我應該擔心,因爲它在第一次運行時會在logcat中給出錯誤消息。 – dreamer1989

+2

@ dreamer1989根據logcat中錯誤消息的內容,您應該擔心。無論哪種方式,問這些錯誤信息是否令人擔憂或不是一個很好的第二個問題。不要讓這個問題做雙重責任。 –

1

你開始使用c.moveToNext()讀取連續值之前,設置光標到初始位置,也就是你的數據庫的開始。

c.moveToFirst()

,然後開始閱讀的形式吧。

可能解決您的問題。

+3

我不同意。沒有要求在moveToNext()之前使用'moveToFirst()'。如果你有一個索引爲-1的新遊標,'moveToNext()'會將索引移動到0並返回true(如果至少有一行)。 – Sam

+0

@Sam:是的,先生,我完全同意你的看法!但是我沒有其他的理由可以在他的代碼中找到將光標移動到-1的位置,並因此給出了我的看法。你的邏輯是正確的,但是爲什麼在第一次運行期間只有錯誤**?這是關於第一次運行中的錯誤的評論,這讓我想到了這一點。還請注意在我的回答中使用了「**」這個詞,因爲我不是SQLite和遊標的主人。 :) – Swayam

+0

我理解你的邏輯,但仔細看看錯誤:'讀取0行,列-1失敗。列索引是'-1'而不是行索引。 – Sam

0

錯誤是在數據庫列名中使用了變音符號ü,ö,ä。

雖然您可以通過切換方法cursor.movetonext()來頻繁切換內容,直到您移動到正確的編號爲止,但這非常煩人並且需要一堆代碼。

我想這應該可以解決大部分人的問題。我猜想除ASCII之外的任何東西都是錯誤的 - 空格,點,否定等都不能使用。

你可以成功地創建一個數據庫,你可以看到外部的sqlite工具,但android會永遠嘮叨。

0

發生這種情況的另一種情況:
在光標仍在使用時,正在刪除遊標中的行。

E.g僞密碼子在那裏它可能發生:

while(cursor.moveToNext()){ 

    readCursor(cursor); 

    deleteRowFromCursor(cursor); 

} 

解決方案:

要刪除的行保持列表;構建批量刪除sql語句;在while循環的外側執行語句(當您完成了使用遊標或關閉它之後)。

while(cursor.moveToNext()){ 

    readCursor(cursor); 

    queueRowForDelete(cursor); 

} 

deleteQueuedRows(queuedRowsList); 
相關問題