SQLite
 sql >> Database >  >> RDS >> SQLite

sqliteLog 14:impossibile aprire il file alla riga

Guida passo passo.

1. Crea il database utilizzando uno strumento di gestione SQLite appropriato con la tabella lyrics popolato con i dati richiesti. Garantire il salvataggio del database.

  • In questo caso è stato utilizzato NaviCat e il seguente SQL è stato utilizzato per creare e popolare la tabella dei testi.

:-

CREATE TABLE IF NOT EXISTS lyrics (
    id INTEGER PRIMARY KEY,
    song TEXT, 
    year TEXT,
    artist TEXT,
    genre TEXT,
    lyrics TEXT
);
INSERT INTO lyrics (song, year, artist, genre, lyrics) VALUES
    ('song1','1970','Fred','Rock','Rock rock rock'),
    ('song2','1980','Mary','Pop','Pop pop pop'),
    ('song3','1960','Sue','Folk','Folk folk folk');
  • Nota indice è una parola chiave, quindi non è un nome di colonna valido a meno che non sia racchiusa, quindi id è stato utilizzato al posto di index.

2. Il file è stato salvato come lyrics.db e copiato nella cartella delle risorse del progetto.

3. DbHelper.java (varie modifiche)

public class DbHelper extends SQLiteOpenHelper {
    
    private static String DB_NAME = "lyrics.db";
    private SQLiteDatabase vDatabase;
    private Context vContext;

    public DbHelper(Context context) {
        super(context, DB_NAME, null, 1);
        this.vContext = context;
        // Copy the DB if need be when instantiating the DbHelper
        if (!checkDataBase()) {
            copyDB();
        }
        vDatabase = this.getWritableDatabase(); //Get the database when instantiating
    }

    /**
     * No need for build version check as getDataBasePath works for all versions
     * No need for open and close of Database, just open it once for the lifetime (more efficient)
     */

    /**
     * Check if the database already exist to avoid re-copying the file each time you open the application.
     * @return true if it exists, false if it doesn't
     */
    private boolean checkDataBase() {
        /**
         * Does not open the database instead checks to see if the file exists
         * also creates the databases directory if it does not exists
         * (the real reason why the database is opened, which appears to result in issues)
         */
        File db = new File(vContext.getDatabasePath(DB_NAME).getPath()); //Get the file name of the database
        Log.d("DBPATH","DB Path is " + db.getPath());
        if (db.exists()) return true; // If it exists then return doing nothing

        // Get the parent (directory in which the database file would be)
        File dbdir = db.getParentFile();
        // If the directory does not exist then make the directory (and higher level directories)
        if (!dbdir.exists()) {
            db.getParentFile().mkdirs();
            dbdir.mkdirs();
        }
        return false;
    }

    public void copyDB() throws SQLiteException{
        try {
            InputStream myInput = vContext.getAssets().open(DB_NAME);
            String outputFileName = vContext.getDatabasePath(DB_NAME).getPath(); //<<<<<<<<<< changed
            Log.d("LIFECYCLE", outputFileName);
            OutputStream myOutput = new FileOutputStream(outputFileName);

            byte[] buffer = new byte[1024];
            int length;
            while( (length=myInput.read(buffer)) > 0 ){
                myOutput.write(buffer, 0, length);
            }
            myOutput.flush();
            myOutput.close();
            myInput.close();
        } catch ( IOException e) {
            e.printStackTrace();
        }
    }

    public List<Lyric> getAllSong(){
        List<Lyric> temp = new ArrayList<>();
        Cursor cursor = vDatabase.query("lyrics",null,null,null,null,null,null);
        //Cursor cursor = db.rawQuery( "SELECT * FROM lyrics" , null); // used query method generally preferred to rawQuery
        //if( cursor == null) return null; // Cursor will not be null may be empty
        //cursor.moveToFirst(); // changed to use simpler loop
        while (cursor.moveToNext()) {
            Lyric lyric = new Lyric(
                    //cursor.getString(cursor.getColumnIndex("index")), //<<<<<<< changed due to column name change
                    cursor.getString(cursor.getColumnIndex("id")),
                    cursor.getString(cursor.getColumnIndex("song")),
                    cursor.getString(cursor.getColumnIndex("year")),
                    cursor.getString(cursor.getColumnIndex("artist")),
                    cursor.getString(cursor.getColumnIndex("genre")),
                    cursor.getString(cursor.getColumnIndex("lyrics"))
            );
            temp.add(lyric);
        }
        cursor.close();
        //db.close(); // inefficient to keep on opening and closing db
        return temp;
    }

    @Override
    public void onCreate(SQLiteDatabase db) {
    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
    }
}
  • Controlla i commenti sulle modifiche

4. Disinstalla l'App esistente o elimina i dati dell'App (IMPORTANTE)

5. Provalo.

Quella che segue è un'attività che metterà alla prova quanto sopra.

public class MainActivity extends AppCompatActivity {

    DbHelper vDBHlpr;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        vDBHlpr = new DbHelper(this);
        List<Lyric> mylyricslist =  vDBHlpr.getAllSong();
        for (Lyric l: mylyricslist) {
            Log.d("LYRICFROMDB","Song is " + l.getSong() + " Year is " + l.getYear() + " Artist is " + l.getArtist() + " Genre is " + l.getGenre() + " Lyrics are " + l.getLyrics());
        }
    }
}

Il registro dovrebbe includere (prima esecuzione) :-

03-17 19:42:11.067 16057-16057/? D/DBPATH: DB Path is /data/data/com.example.so55199382lyrics/databases/lyrics.db
03-17 19:42:11.067 16057-16057/? D/LIFECYCLE: /data/data/com.example.so55199382lyrics/databases/lyrics.db
03-17 19:42:11.086 16057-16057/? D/LYRICFROMDB: Song is song1 Year is 1970 Artist is Fred Genre is Rock Lyrics are Rock rock rock
03-17 19:42:11.086 16057-16057/? D/LYRICFROMDB: Song is song2 Year is 1980 Artist is Mary Genre is Pop Lyrics are Pop pop pop
03-17 19:42:11.086 16057-16057/? D/LYRICFROMDB: Song is song3 Year is 1960 Artist is Sue Genre is Folk Lyrics are Folk folk folk

o per le esecuzioni successive :-

03-17 19:49:11.275 16136-16136/? D/DBPATH: DB Path is /data/data/com.example.so55199382lyrics/databases/lyrics.db
03-17 19:49:11.279 16136-16136/? D/LYRICFROMDB: Song is song1 Year is 1970 Artist is Fred Genre is Rock Lyrics are Rock rock rock
03-17 19:49:11.279 16136-16136/? D/LYRICFROMDB: Song is song2 Year is 1980 Artist is Mary Genre is Pop Lyrics are Pop pop pop
03-17 19:49:11.279 16136-16136/? D/LYRICFROMDB: Song is song3 Year is 1960 Artist is Sue Genre is Folk Lyrics are Folk folk folk
  • La nota viene eseguita due volte in modo da controllare sia il processo di copia che la gestione del db esistente.

Quanto sopra è stato testato su emulatori con Android Lollipop e Pie