Recuperar blob grande de la base de datos sqlite de Android

Guardé trozos de datos binarios (protobufs) en la base de datos sqlite de una aplicación de Android sin darme cuenta de que el Cursor de Android solo puede contener un máximo de 1MB de datos. Ahora sé que debería haber almacenado estos blobs binarios en archivos y solo hice referencia a los archivos en las entradas de la base de datos sqlite.

Necesito actualizar la base de datos (la aplicación ha estado en uso por un tiempo) para mover estos fragmentos binarios a los archivos. El problema es que los datos de algunos usuarios pueden haber excedido el límite de 1MB y no puedo recuperarlos de la base de datos (accediendo al Cursor resultante para una sola fila que contiene un blob grande se lanza una IllegalStateException: Couldn't read row 0, col 0 from CursorWindow. Make sure the Cursor is initialize before accessing data from it ).

¿Cómo recupero los blobs binarios que son mayores que el límite del Cursor 1MB que se ha almacenado en la base de datos sqlite?

Puedes leer manchas grandes en pedazos. Primero averigüe cuáles necesitan este tratamiento:

 SELECT id, length(blobcolumn) FROM mytable WHERE length(blobcolumn) > 1000000 

y luego lea los fragmentos con substr :

 SELECT substr(blobcolumn, 1, 1000000) FROM mytable WHERE id = 123 SELECT substr(blobcolumn, 1000001, 1000000) FROM mytable WHERE id = 123 ... 

También podría comstackr su propia copia de SQLite y acceder a las funciones de E / S de flujo BLOB o a las funciones de consulta normales de la API C con el NDK, pero eso sería demasiado complejo en este caso.

CL. la respuesta solo con blobs <5MB. Si intentas usarlo con manchas de más de 5 megabytes, aún obtendrás la excepción. Para buscar blobs grandes, necesita usar una biblioteca llamada sqlite4java que usa llamadas nativas a la base de datos sin usar cursores. Aquí hay un ejemplo del uso de esta biblioteca para obtener un blob grande:

 SQLiteConnection sqLiteConnection=null; SQLiteStatement sqLiteStatement=null; try { File databaseFile = context.getDatabasePath("database.db"); sqLiteConnection=new SQLiteConnection(databaseFile); sqLiteConnection.open(); sqLiteStatement=sqLiteConnection.prepare("SELECT blob FROM table WHERE id=?"); sqLiteStatement.bind(1, id); sqLiteStatement.step(); byte[] blob=sqLiteStatement.columnBlob(0); } finally { if(sqLiteStatement!=null) sqLiteStatement.dispose(); if(sqLiteConnection!=null) sqLiteConnection.dispose(); }