2012-10-03 16 views
17

Przechowywałem fragmenty danych binarnych (protobufs) w bazie danych sqlite aplikacji na Androida, nie zdając sobie sprawy, że Android Cursor może pomieścić maksymalnie 1 MB danych. Teraz wiem, że powinienem przechowywać te binarne obiekty blob w plikach i odwoływać się tylko do plików w wpisach bazy danych sqlite.Odzyskaj dużą plamę z bazy danych Android sqlite

Potrzebuję zaktualizować bazę danych (aplikacja była używana przez jakiś czas), aby przenieść te fragmenty binarne do plików. Problem polega na tym, że niektóre dane użytkownika mogły już przekroczyć limit 1 MB i nie mogę odzyskać go z bazy danych (dostęp do uzyskanego wyniku Cursor dla pojedynczego wiersza zawierającego dużą kropelkę powoduje wyświetlenie IllegalStateException: Couldn't read row 0, col 0 from CursorWindow. Make sure the Cursor is initialize before accessing data from it).

Jak mogę pobrać binarne obiekty blob, które są większe niż limit 1 MB Cursor, które zostały zapisane w bazie danych sqlite?

+0

Hej, dzięki! To pytanie pomogło mi przeanalizować i rozwiązać ten sam problem, z którym miałem do czynienia! –

Odpowiedz

27

Możesz przeczytać duże obiekty w kawałkach. Najpierw dowiedzieć się, które z nich trzeba ten zabieg:

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

a następnie odczytać fragmenty z substr:

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

Można również przygotować własną kopię SQLite oraz dostęp albo BLOB stream I/O funkcji lub jeżeli normalne funkcje zapytań C API z NDK, ale w tym przypadku byłoby to zbyt skomplikowane.

+0

Dziękuję bardzo! To naprawdę pomogło. Nie miałem pojęcia o podstawowych funkcjach SQLite. Działa doskonale! – ashughes

+0

Czy masz skuteczny sposób dodawania tych fragmentów, aby utworzyć cały "bajt []"? –

+0

@KamranAhmed Znasz już całą długość, więc przydziel dużą tablicę i skopiuj porcje. –

0

CL. odpowiedź będzie tylko z plamami < 5MB. Jeśli spróbujesz użyć go z obiektami typu blob większymi niż 5 megabajtów, nadal otrzymasz wyjątek. Aby pobrać duże obiekty BLOB, należy użyć biblioteki o nazwie sqlite4java, która wykorzystuje natywne wywołania do bazy danych bez użycia kursorów. Oto przykład użycia tej biblioteki do pobrania dużego obiektu:

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(); 
}