androidandroid-sqliteandroid-cursorjagged-arrays

Unable to retrieve entire contents of Cursor due to CursorIndexOutOfBoundsException (to put into jagged array of strings)


I'm trying to get the contents of a cursor and put them into a 2d string for usage later in my app. To do this, I've written the following function:

public String[][] cursorTo2dString (Cursor cursor) {

    int columnCount = cursor.getColumnCount();
    int count = cursor.getCount();
    String[][] string2dArray = new String[count][columnCount];
    Log.i("StringLengths", count + " & " + columnCount);
    Log.i("CursorConts", DatabaseUtils.dumpCursorToString(cursor));
    if (cursor.moveToFirst())
    {
        for (int j=0; j<count && !cursor.isAfterLast(); j++)
        {
            for (int i=0; i<columnCount; i++)
            {
                Log.i("Cursor", cursor.getString(i));
                string2dArray[j][i] = cursor.getString(i);
                Log.i("StringPoint", string2dArray[j][i]);
            }
            cursor.moveToNext();
        }
    }

    return string2dArray;
}

This is giving me the following results in the console when the program crashes

I/StringLengths: 1 & 2
I/CursorConts: >>>>> Dumping cursor android.database.sqlite.SQLiteCursor@f7e2e6f
               0 {
                  TagIdNo=3866
                  TagName=No Parental Permission
               }
               <<<<<
I/Cursor: 3866
I/StringPoint: 3866
I/Cursor: No Parental Permission
I/StringPoint: No Parental Permission
I/MovePos: true & false
E/AndroidRuntime: FATAL EXCEPTION: main
                  Process: com.example.programming.workingpomproject, PID: 29771
                  java.lang.IllegalStateException: Could not execute method for android:onClick
                      at android.support.v7.app.AppCompatViewInflater$DeclaredOnClickListener.onClick(AppCompatViewInflater.java:293)
                      at android.view.View.performClick(View.java:5226)
                      at android.view.View$PerformClick.run(View.java:21266)
                      at android.os.Handler.handleCallback(Handler.java:739)
                      at android.os.Handler.dispatchMessage(Handler.java:95)
                      at android.os.Looper.loop(Looper.java:168)
                      at android.app.ActivityThread.main(ActivityThread.java:5845)
                      at java.lang.reflect.Method.invoke(Native Method)
                      at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:797)
                      at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:687)
                   Caused by: java.lang.reflect.InvocationTargetException
                      at java.lang.reflect.Method.invoke(Native Method)
                      at android.support.v7.app.AppCompatViewInflater$DeclaredOnClickListener.onClick(AppCompatViewInflater.java:288)
                      at android.view.View.performClick(View.java:5226) 
                      at android.view.View$PerformClick.run(View.java:21266) 
                      at android.os.Handler.handleCallback(Handler.java:739) 
                      at android.os.Handler.dispatchMessage(Handler.java:95) 
                      at android.os.Looper.loop(Looper.java:168) 
                      at android.app.ActivityThread.main(ActivityThread.java:5845) 
                      at java.lang.reflect.Method.invoke(Native Method) 
                      at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:797) 
                      at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:687) 
                   Caused by: android.database.CursorIndexOutOfBoundsException: Index 1 requested, with a size of 1
                      at android.database.AbstractCursor.checkPosition(AbstractCursor.java:460)
                      at android.database.AbstractWindowedCursor.checkPosition(AbstractWindowedCursor.java:136)
                      at android.database.AbstractWindowedCursor.getString(AbstractWindowedCursor.java:50)
                      at com.example.programming.workingpomproject.DbHelper.cursorTo2dString(DbHelper.java:155)
                      at com.example.programming.workingpomproject.DbHelper.select(DbHelper.java:89)
                      at com.example.programming.workingpomproject.DbHelper.select(DbHelper.java:92)
                      at com.example.programming.workingpomproject.MainActivity.testDbMethodGet(MainActivity.java:66)
                      at com.example.programming.workingpomproject.MainActivity.dbStuff(MainActivity.java:61)
                      at java.lang.reflect.Method.invoke(Native Method) 
                      at android.support.v7.app.AppCompatViewInflater$DeclaredOnClickListener.onClick(AppCompatViewInflater.java:288) 
                      at android.view.View.performClick(View.java:5226) 
                      at android.view.View$PerformClick.run(View.java:21266) 
                      at android.os.Handler.handleCallback(Handler.java:739) 
                      at android.os.Handler.dispatchMessage(Handler.java:95) 
                      at android.os.Looper.loop(Looper.java:168) 
                      at android.app.ActivityThread.main(ActivityThread.java:5845) 
                      at java.lang.reflect.Method.invoke(Native Method) 
                      at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:797) 
                      at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:687) 

Any advice as to how to resolve this, and any amendments to my method, would be greatly appreciated.

Thanks for any and all help! I apologise for any issues with my coding standards, this is my first android app and my first time in Java, though I've written in C# before.

Edit1:

The exception thus far is appearing on the line

if (cursor.moveToFirst()) //line 117

or at least this is the line that is highlighted by Android Studio's debugger. I suspect that the exception isn't in fact occurring here because this line number is 117 and the if statement ends on line 129, neither of which actually appear in the debugger; also, the program flow is jumping straight to here from the line

Log.i("Cursor", cursor.getString(i)); //line 123

once i is equal to 2 whilst j is equal to 0. This is shown by the fact that the breakpoints I leave on the two following lines go untriggered in this iteration of the inner loop.

I've amended the code section above to show the current situation. These amendments consist of removing the last two Log.i statements that existed before. These were as follows

Log.i("MovePos", String.valueOf(cursor.isAfterLast()) + " & " + cursor.moveToPosition(cursor.getColumnIndex("TagName")));
    Log.i("LOOK HERE", cursor.getString(0));

Which never got ran anyhow according to the console log.


Solution

  • The following works for me.

    public String[][] makeArrayFromCursor(Cursor csr) {
    
           String[][] rv = new String[csr.getCount()][csr.getColumnCount()];
           if (csr.getCount() > 0) {
               int called_pos = csr.getPosition();
               csr.moveToPosition(-1);
               while (csr.moveToNext()) {
                   for (int i=0; i < csr.getColumnCount(); i++) {
                       rv[csr.getPosition()][i] = csr.getString(i);
                   }
               }
               csr.moveToPosition(called_pos);
           }
    
           return rv;
       }
    

    Notes