Android SQLite:W / System.err:java.io.FileNotFoundException无法从资产复制数据库

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android SQLite:W / System.err:java.io.FileNotFoundException无法从资产复制数据库相关的知识,希望对你有一定的参考价值。

我创建了一个包含几个表的数据库。

我已将此数据库保存在资产文件夹中。

我试图从该数据库中简单地访问EXERCISESTABLE,然后在修改后的listView中显示其值。但是,我不断收到错误:

 W/System.err: java.io.FileNotFoundException.

这是我的MainActivity扩展的活动类:

@Override
protected void onCreate(Bundle savedInstanceState) 
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    lvExercise = (ListView)findViewById(R.id.listView_exercises);
    mDBHelper = new DatabaseHelper(this);

    //Check exists database
    File database = getApplicationContext().getDatabasePath(DatabaseHelper.DBNAME);
    if(false == database.exists())
        mDBHelper.getReadableDatabase();

        // Copy Database
        if(copyDatabase(this))
            Toast.makeText(this, "Copy database success", Toast.LENGTH_SHORT).show();
        else 
            Toast.makeText(this, "Copy data error", Toast.LENGTH_SHORT).show();
            return;
        
    
    //Get exercise List in db when db exists
    mExercisesList = mDBHelper.getListExercise();
    //Init adapter
    adapter = new ListExerciseAdapter(this, mExercisesList);
    //Set adapter for list view
    lvExercise.setAdapter(adapter);



private boolean copyDatabase(Context context)
    try
        InputStream inputStream = context.getAssets().open(DatabaseHelper.DBNAME);
        String outFileName = DatabaseHelper.DBLOCATION + DatabaseHelper.DBNAME;
        OutputStream outputStream = new FileOutputStream(outFileName);
        byte[]buff = new byte[1024];
        int length =0;
        while ((length = inputStream.read(buff)) >0)
            outputStream.write(buff, 0, length);
        
        outputStream.flush();
        outputStream.close();
        Log.w("MainActivity", "DB copied");
        return true;

    catch(Exception e)
        e.printStackTrace();
        return false;
    

我在assets文件夹中有我的execution_program.db数据库文件,但是即使看起来对我来说我似乎都无法访问它。

这里是我的DBHelper扩展了SQLiteOpenHelper代码:

private Context mContext;
private SQLiteDatabase mDatabase;

public DatabaseHelper(Context context)
    super(context, DBNAME, null, 1);
    this.mContext = context;


@Override
public void onCreate(SQLiteDatabase db) 




@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) 


public void openDatabase() 
    String dbPath = mContext.getDatabasePath(DBNAME).getPath();
    if(mDatabase != null && mDatabase.isOpen())
        return;
    
    mDatabase = SQLiteDatabase.openDatabase(dbPath,null,SQLiteDatabase.OPEN_READWRITE);


public void closeDatabase()
    if(mDatabase!=null)
        mDatabase.close();
    


public List<Exercise> getListExercise()
    Exercise exercise = null;
    List<Exercise> exerciseList = new ArrayList<>();
    openDatabase();
    Cursor cursor = mDatabase.rawQuery("SELECT * FROM EXERCISESTABLE ", null);
    cursor.moveToFirst();
    while(!cursor.isAfterLast())
        exercise = new Exercise(cursor.getInt(0),cursor.getString(1), cursor.getInt(2), cursor.getInt(3));
        exerciseList.add(exercise);
        cursor.moveToNext();
        closeDatabase();

    
    return exerciseList;

这是我的运动课:

public class Exercise 
private int exercise_id;
private String exercise_name;
private int exercise_type_id;
private int exercise_equipment_id;

public Exercise(int exercise_id, String exercise_name, int exercise_type_id, int exercise_equipment_id) 
    this.exercise_id = exercise_id;
    this.exercise_name = exercise_name;
    this.exercise_type_id = exercise_type_id;
    this.exercise_equipment_id = exercise_equipment_id;


public int getExercise_id() 
    return exercise_id;


public void setExercise_id(int exercise_id) 
    this.exercise_id = exercise_id;


public String getExercise_name() 
    return exercise_name;


public void setExercise_name(String exercise_name) 
    this.exercise_name = exercise_name;


public int getExercise_type_id() 
    return exercise_type_id;


public void setExercise_type_id(int exercise_type_id) 
    this.exercise_type_id = exercise_type_id;


public int getExercise_equipment_id() 
    return exercise_equipment_id;


public void setExercise_equipment_id(int exercise_equipment_id) 
    this.exercise_equipment_id = exercise_equipment_id;

这是我的ListExerciseAdapter扩展BaseAdapter类:

public ListExerciseAdapter(Context mContext, List<Exercise> exercisesList) 
    this.mContext = mContext;
    this.mExercisesList = exercisesList;


@Override
public int getCount() 
    return mExercisesList.size();


@Override
public Object getItem(int position) 
    return mExercisesList.get(position);


@Override
public long getItemId(int position) 
    return mExercisesList.get(position).getExercise_id();


@Override
public View getView(int position, View convertView, ViewGroup parent) 

    View v = View.inflate(mContext, R.layout.exercises_listview_layout, null);
    TextView exercise_name = (TextView)v.findViewById(R.id.exercise_name);
    TextView exercise_type_id = (TextView)v.findViewById(R.id.exercise_type_id);
    TextView exercise_equipment_id = (TextView)v.findViewById(R.id.exercise_equipment_id);

    exercise_name.setText(mExercisesList.get(position).getExercise_name());
    exercise_type_id.setText(String.valueOf(mExercisesList.get(position).getExercise_type_id()));
    exercise_equipment_id.setText(String.valueOf(mExercisesList.get(position).getExercise_equipment_id()));
    return v;

任何帮助将不胜感激。

答案

根据official documentation中预先填充的房间数据库。您有2个选项:

1] createFromAssets:在此选项中,您可以在资产文件夹下创建一个名为“数据库”的目录因此您可能会如下所示:

.createFromAssets("/databases/YOUR DATABASE FILENAME")

2)createFromFile:此选项可能与您为其分配路径的文件一起使用。

.createFromFile(File("YOUR FILE PATH"))

如果您对这两种解决方案感到困惑,可以尝试使用手动解决方案,我们可以将其称为手动解决方案!通过访问资产文件夹中的数据库文件。

    private fun copyDBFromStorage(databaseName: String) 
    if (checkIfDBExists(this, databaseName)) return
    val databaseFile = File(this.getDatabasePath(databaseName).toString())
    val sourceLocation = assets.open("Your database file path")
    try 
        val inputStream = sourceLocation
        val os = FileOutputStream(databaseFile)
        val buffer = ByteArray(1024 * 32)
        var length = inputStream.read(buffer)
        while (length > 0) 
            os.write(buffer, 0, length)
            length = inputStream.read(buffer)
        
        os.flush()
        os.close()
        inputStream.close()

     catch (ex: IOException) 
        ex.printStackTrace();
        throw  RuntimeException("Error copying storage database");
    


private fun checkIfDBExists(
    context: Context,
    databaseName: String
): Boolean 
    val dbfile = File(context.getDatabasePath(databaseName).toString())
    if (dbfile.exists()) return true
    if (!dbfile.parentFile.exists()) 
        dbfile.parentFile.mkdirs()
    
    return false

Note:您可以使用android Studio代码转换功能将此Kotlin代码转换为Java。

如果发现任何问题,请回复。

快乐编码

以上是关于Android SQLite:W / System.err:java.io.FileNotFoundException无法从资产复制数据库的主要内容,如果未能解决你的问题,请参考以下文章

Android Sqlite3 not found

android用真机测试用不了sqlite3,push的时候一直提示Read-only file system,求帮助

SQLite操作总结

Android开发—错误记录1:W/System.err: java.net.ConnectException: Connection refused

Android:将 sqlite 数据库内容加载到 webview

Android SQLite LIKE 转义通配符