Android SQLite:W/System.err:java.io.FileNotFoundException 无法从资产复制数据库
Android SQLite: W/System.err: java.io.FileNotFoundException Cannot copy database from assets
我创建了一个包含多个表的数据库。
我将这个数据库保存在资产文件夹中。
我试图简单地从此数据库访问 EXERCISESTABLE,然后在修改后的 listView 中显示它的值。
但是,我不断收到错误消息:
W/System.err: java.io.FileNotFoundException.
这是我的 MainActivity extends Activity Class:
@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;
}
}
我的 workout_program.db 数据库文件位于 assets 文件夹中,但我似乎无法访问它,尽管它对我来说看起来都是正确的。
这是我的 DBHelper extends 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;
}
这是我的练习class:
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 extends BaseAdapter class:
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: 在此选项中,您可以在 assets 文件夹下创建一个名为 "databases" 的目录
所以你可以如下:
.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
}
注意:您可以使用 android studio 代码转换功能将此 Kotlin 代码转换为 java。
如果您发现任何问题,请回复。
编码愉快
我创建了一个包含多个表的数据库。
我将这个数据库保存在资产文件夹中。
我试图简单地从此数据库访问 EXERCISESTABLE,然后在修改后的 listView 中显示它的值。 但是,我不断收到错误消息:
W/System.err: java.io.FileNotFoundException.
这是我的 MainActivity extends Activity Class:
@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;
}
}
我的 workout_program.db 数据库文件位于 assets 文件夹中,但我似乎无法访问它,尽管它对我来说看起来都是正确的。
这是我的 DBHelper extends 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;
}
这是我的练习class:
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 extends BaseAdapter class:
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: 在此选项中,您可以在 assets 文件夹下创建一个名为 "databases" 的目录 所以你可以如下:
.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
}
注意:您可以使用 android studio 代码转换功能将此 Kotlin 代码转换为 java。
如果您发现任何问题,请回复。
编码愉快