entre Desarrolladores

Recibe ayuda de expertos

Registrate y pregunta

Es gratis y fácil

Recibe respuestas

Respuestas, votos y comentarios

Vota y selecciona respuestas

Recibe puntos, vota y da la solución

Pregunta

2votos

Erro al volcar datos de un fichero con extensión .db pero sí funciona

Hola.

Recibo el siguiente error al volcar los datos de un fichero llamado instalacionesdep.db. Lo curioso es, que se carga todo correctamente, pero en el logcat recibo el siguiente error.

12-11 13:05:54.284: E/SqliteDatabaseCpp(17232): sqlite3_open_v2("data/data/com.mipaquete.instalacionesdep/databases/instalacionesdep.db", &handle, 1, NULL) failed
12-11 13:05:54.354: E/SQLiteDatabase(17232): Failed to open the database. closing it.
12-11 13:05:54.354: E/SQLiteDatabase(17232): android.database.sqlite.SQLiteCantOpenDatabaseException: unable to open database file
12-11 13:05:54.354: E/SQLiteDatabase(17232):   at android.database.sqlite.SQLiteDatabase.dbopen(Native Method)
12-11 13:05:54.354: E/SQLiteDatabase(17232):     at android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:1013)
12-11 13:05:54.354: E/SQLiteDatabase(17232):    at android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:986)
12-11 13:05:54.354: E/SQLiteDatabase(17232):     at android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:962)
12-11 13:05:54.354: E/SQLiteDatabase(17232):     at com.mipaquete.instalacionesdep.db.DataBaseHelper.checkDataBase(DataBaseHelper.java:99)
12-11 13:05:54.354: E/SQLiteDatabase(17232):   at com.mipaquete.instalacionesdep.db.DataBaseHelper.createDataBase(DataBaseHelper.java:72)
12-11 13:05:54.354: E/SQLiteDatabase(17232):  at com.mipaquete.instalacionesdep.db.TodasLasInstalacionesActivity.onClick(TodasLasInstalacionesActivity.java:71)
12-11 13:05:54.354: E/SQLiteDatabase(17232):   at android.view.View.performClick(View.java:3511)
12-11 13:05:54.354: E/SQLiteDatabase(17232):   at android.view.View$PerformClick.run(View.java:14105)
12-11 13:05:54.354: E/SQLiteDatabase(17232):      at android.os.Handler.handleCallback(Handler.java:605)
12-11 13:05:54.354: E/SQLiteDatabase(17232):      at android.os.Handler.dispatchMessage(Handler.java:92)
12-11 13:05:54.354: E/SQLiteDatabase(17232):      at android.os.Looper.loop(Looper.java:137)
12-11 13:05:54.354: E/SQLiteDatabase(17232):  at android.app.ActivityThread.main(ActivityThread.java:4424)
12-11 13:05:54.354: E/SQLiteDatabase(17232):        at java.lang.reflect.Method.invokeNative(Native Method)
12-11 13:05:54.354: E/SQLiteDatabase(17232):     at java.lang.reflect.Method.invoke(Method.java:511)
12-11 13:05:54.354: E/SQLiteDatabase(17232):         at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:784)
12-11 13:05:54.354: E/SQLiteDatabase(17232):  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:551)
12-11 13:05:54.354: E/SQLiteDatabase(17232):     at dalvik.system.NativeStart.main(Native Method)

Parece que debo de cerrar en algún momento el myDbhelper, pero yo creo que realizo todos los pasos y no encuentro el fallo. Este es el código resumido de mi clase DataBaseHelper que extiende de SQLiteOpenHelper.

public class DataBaseHelper extends SQLiteOpenHelper {

    //Variables ausiliares
    private static String DB_PATH="data/data/com.mipaquete.instalacionesdep/databases/";
    private static final String DB_NAME="instalacionesdep.db";
    //private static final int DATABASE_VERSION =1;

    private SQLiteDatabase myDatabase;
    private final Context myContext;

    public DataBaseHelper(Context context) {
        super(context, DB_NAME, null, 1);
        // TODO Auto-generated constructor stub
        this.myContext = context; 
    }

    public void createDataBase() throws IOException{
        //para chequear que existe la BD
        boolean dbExist = checkDataBase();

        SQLiteDatabase db_read = null;

        if(dbExist){

        }else{
            //agarramos la BD para leerla y despues la cerramos. 
            db_read = this.getReadableDatabase();
            db_read.close();

            try {
                copyDataBase();
            } catch (Exception e) {
                // TODO: handle exception
                throw new Error("Error copying database (createDataBase)");
            }
        }

    }

    public boolean checkDataBase(){
        SQLiteDatabase checkDB = null;
        SQLiteDatabase db_read = null;

        try{
            String myPath = DB_PATH+DB_NAME;
            checkDB = SQLiteDatabase.openDatabase(myPath, null, SQLiteDatabase.OPEN_READONLY);
        }catch (SQLException e) {
            // TODO: handle exception
            File dbFile = new File(DB_PATH+DB_NAME);
            return dbFile.exists();
        }
        if(checkDB != null){
            checkDB.close();

        }

        //regresa un true o un false dependidendo si se cumple la condicion. Los : sustituyen al else
        return checkDB != null ? true : false;
    }

    //vamos a volcar 
    public void copyDataBase() throws IOException{

        InputStream myInput = myContext.getAssets().open(DB_NAME);
        String outFileName = DB_PATH+DB_NAME;

        OutputStream myOutPut = new FileOutputStream(outFileName);

        Log.e("LocAndroid", "ESTOY EN copyDataBase");

        //Para trasnferir el fichero en tamaños de 1024 bytes
        byte[] buffer = new byte[1024];
        int lenght;

        //while para que nos mande el archivo. 
        while((lenght = myInput.read(buffer))!=-1){
            if(lenght > 0){
                myOutPut.write(buffer, 0, lenght);
            //con esto hemos copiado la base de datos. Basicamente, El volcado del archivo

            }

        }
        myOutPut.flush();
        myOutPut.close();
        myInput.close();
    }

    //Para abrir la base de datos
    public void openDataBase() throws SQLException{

        //myDatabase = this.getWritableDatabase();
        String myPath = DB_PATH+DB_NAME;
        myDatabase = SQLiteDatabase.openDatabase(myPath, null, SQLiteDatabase.OPEN_READWRITE);
    }

    //Para cerrar la base de datos
    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) {
        // TODO Auto-generated method stub

    }

}

Gracias y saludos.

0voto

egoitz_gonzalez comentado

Me he dado cuenta que si sustituyo el código de checkDatabase() por el siguiente código no da ningún error.

public boolean databaseExist()

{
    File dbFile = new File(DB_PATH + DB_NAME);
    return dbFile.exists();
}

Con lo cual el erro salta en el try de checkDatabase. Entonces el error se produce en la siguientes lineas:

String myPath = DB_PATH+DB_NAME;
            checkDB = SQLiteDatabase.openDatabase(myPath, null, SQLiteDatabase.OPEN_READONLY);

Pero la verdad es que no sé solucionarlo

1 Respuesta

2votos

Leonardo-Tadei Puntos227320

Hola Egoitz,

parece que el fallo está en tu método checkDataBase() ya que verifica si la DB existe intentando abrirla, y al abrirla se producen los errores.

Lo ideal sería verificar si el archivo existe invocando a las funciones de manejo de archivos y no a las de SQLite, ya que además un OpenDatabase() te creará una DB nueva si no existe, y tu condición para saber si se debe descargar o no el archivo es justamente que no exista, con lo que si hay un fallo de conexión, la app ya tendría el archivo crado (vacío) y no lo intentaría volver a descargar.

Poner un código en un bloque TRY no hace que el error no se produzca y está bien que lo veas en el log. Lo que hace un bloque TRY es permitirte manejar el error cuando se produce para impedir que se aborte la ejecución de la aplicación.

Saludos!

0voto

egoitz_gonzalez comentado

Hola. Sí estoy de acuerdo que el try es para gestionar los errores cuando se producen. El caso es que la primera vez que se ejecuta checkDatabase() salta el error en el try porque la base de datos no existe.

try{

            String myPath = DB_PATH+DB_NAME;
            checkDB = SQLiteDatabase.openDatabase(myPath, null, SQLiteDatabase.OPEN_READONLY);
        }catch (SQLException e) {
            // TODO: handle exception
            //database does't exist yet.
            File dbFile = new File(DB_PATH+DB_NAME);
            return dbFile.exists();

        } 

Por ello al saltar ese try trato el problema en createDataBase() y creo la base de datos.

public void createDataBase() throws IOException{
        //para chequear que existe la BD
        boolean dbExist = checkDataBase();

        SQLiteDatabase db_read = null;

        if(dbExist){
            //Do nothing

        }else{
            //agarramos la BD para leerla y despues la cerramos. 
            db_read = this.getReadableDatabase();

            try {
                copyDataBase();
            } catch (Exception e) {
                // TODO: handle exception
                throw new Error("Error copying database (createDataBase)");
            }db_read.close();
        }

    }

Por eso después sí se crea bien la base de datos y todo funciona correcto. Pero imagino que el error del mencionado try en la primera ejecución se podrá corregir. Pero no se como.

0voto

Leonardo-Tadei comentado

Egoitz,

para que no te de error en el primer chequeo, en vez de preguntar si la DB existe con:

String myPath = DB_PATH+DB_NAME;
checkDB = SQLiteDatabase.openDatabase(myPath, null, SQLiteDatabase.OPEN_READONLY);

hacelo con:

File dbFile = new File(DB_PATH + DB_NAME);
return dbFile.exists();

como lo planteás en tu comentario. Esta es una implementación mucho mejor de checkDataBase()

Una DB SQLite es simplemente un archivo (con un formato específico) así que preguntar si el archivo existe es perfectamenet viable, porque solo implica la asunción de que de existir será un DB válido.

Saludos!

0voto

egoitz_gonzalez comentado

Hola Leonardo.

Sí tienes toda la razón. Con el código;

String myPath = DB_PATH+DB_NAME;
checkDB = SQLiteDatabase.openDatabase(myPath, null, SQLiteDatabase.OPEN_READONLY)

Se intenta abrir la base de datos. Si da error, se da por supuesto que la base de datos no existe y se crea. Pero lógicamente esta implementación siempre dará error en su primera ejecución.

Por ello, tal como me comentas lo mas fácil es mirar si el fichero existe en el path especificado, ya que la base de datos es un simple fichero .db . Estaba mezclando el fichero .db alojado en la carpeta assets con el alojado en data/data/com.mipaquete.instalacionesdep/databases/ .

Gracias y saludos!

Por favor, accede o regístrate para responder a esta pregunta.

Otras Preguntas y Respuestas


...

Bienvenido a entre Desarrolladores, donde puedes realizar preguntas y recibir respuestas de otros miembros de la comunidad.

Conecta