FileNotFoundException SQLite 数据库 Android
Posted
技术标签:
【中文标题】FileNotFoundException SQLite 数据库 Android【英文标题】:FileNotFoundException SQLite database Android 【发布时间】:2020-01-16 14:23:37 【问题描述】:我正在尝试从现有的 SQlite 数据库加载数据,但它会抛出“FileNotFoundException”错误
“W/System.err: java.io.FileNotFoundException: cc_recipes.db”
所以我的应用程序在列表视图中显示食谱名称和图像。
我上次已经使用 Eclipse 创建了这个应用程序,它工作得非常好,但是当我使用 android Studio 更改它时。我不能只找到导致错误的原因
我确实在这里找到了一些解决方案,但它也不起作用
谁能帮帮我,拜托!
这是我的代码:
package com.mypackage.example;
import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.util.ArrayList; import android.content.Context; import android.database.Cursor; import android.database.SQLException; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteException; import android.database.sqlite.SQLiteOpenHelper; import android.util.Log;
public class DBHelper extends SQLiteOpenHelper
private static String DB_PATH = "";
private final static String DB_NAME = "cc_recipes.db";
public final static int DB_VERSION = 1;
public static SQLiteDatabase db;
private Context mContext;
private final String TABLE_NAME = "recettes";
private final String ID = "id";
private final String RECIPE_NAME = "title";
private final String IMAGE_PREVIEW = "image_preview";
private final String INGREDIENTS = "ingredients";
private final String DIRECTIONS = "preparation";
public DBHelper(Context context)
super(context, DB_NAME, null, DB_VERSION);
if (android.os.Build.VERSION.SDK_INT >= 17)
//E:\new folders\My study\Projet Ouafae Kandoussi\YammyCook\app\src\main\assets\databases\cc_recipes.db
DB_PATH = context.getApplicationInfo().dataDir + "/databases/";
else
DB_PATH = "/data/data/" + context.getPackageName() + "/databases/";
this.mContext = context;
Log.i("msg","Here my msg: "+DB_PATH);
try
copyDataBase();
catch (IOException e)
e.printStackTrace();
this.getReadableDatabase();
public void createDataBase() throws IOException
boolean dbExist = checkDataBase();
if (dbExist)
// do nothing - database already exist
// check if we need to upgrade
openDataBase();
int cVersion = db.getVersion();
if(cVersion != 2)
onUpgrade(db, db.getVersion(), 2);
close();
else
// By calling this method and empty database will be created into
// the default system path
// of your application so we are gonna be able to overwrite that
// database with our database.
this.getReadableDatabase();
try
copyDataBase();
catch (IOException e)
throw new Error("Error copying database");
private void deleteDataBase()
File dbFile = new File(DB_PATH + DB_NAME);
dbFile.delete();
private boolean checkDataBase()
SQLiteDatabase checkDB = null;
try
String myPath = DB_PATH + DB_NAME;
checkDB = SQLiteDatabase.openDatabase(myPath, null, SQLiteDatabase.OPEN_READWRITE);
catch (SQLiteException e)
// database does't exist yet.
if (checkDB != null)
checkDB.close();
return checkDB != null ? true : false;
private void copyDataBase() throws IOException
InputStream myInput = mContext.getAssets().open(DB_NAME);
String outFileName = DB_PATH + DB_NAME;
OutputStream myOutput = new FileOutputStream(outFileName);
byte[] buffer = new byte[1024];
int length;
while ((length = myInput.read(buffer))>0)
myOutput.write(buffer, 0, length);
myOutput.flush();
myOutput.close();
myInput.close();
public void openDataBase() throws SQLException
String myPath = DB_PATH + DB_NAME;
db = SQLiteDatabase.openDatabase(myPath, null, SQLiteDatabase.OPEN_READWRITE);
@Override
public void close()
db.close();
@Override
public void onCreate(SQLiteDatabase db)
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion)
/** this code is used to get all data from database */
public ArrayList<ArrayList<Object>> getAllData(String RecipeNameKeyword)
ArrayList<ArrayList<Object>> dataArrays = new ArrayList<ArrayList<Object>>();
Cursor cursor = null;
if(RecipeNameKeyword.equals(""))
try
cursor = db.query(
TABLE_NAME,
new String[]ID, RECIPE_NAME, IMAGE_PREVIEW,
null, null, null, null, null);
cursor.moveToFirst();
if (!cursor.isAfterLast())
do
ArrayList<Object> dataList = new ArrayList<Object>();
dataList.add(cursor.getLong(0));
dataList.add(cursor.getString(1));
dataList.add(cursor.getString(2));
dataArrays.add(dataList);
while (cursor.moveToNext());
cursor.close();
catch (SQLException e)
Log.e("DB Error", e.toString());
e.printStackTrace();
else
try
cursor = db.query(
TABLE_NAME,
new String[]ID, RECIPE_NAME, IMAGE_PREVIEW,
RECIPE_NAME +" LIKE '%"+RecipeNameKeyword+"%'",
null, null, null, null);
cursor.moveToFirst();
if (!cursor.isAfterLast())
do
ArrayList<Object> dataList = new ArrayList<Object>();
dataList.add(cursor.getLong(0));
dataList.add(cursor.getString(1));
dataList.add(cursor.getString(2));
dataList.add(cursor.getString(3));
dataArrays.add(dataList);
while (cursor.moveToNext());
cursor.close();
catch (SQLException e)
Log.e("DB Error", e.toString());
e.printStackTrace();
return dataArrays;
// public ArrayList<Object> getRandomData() // ArrayList<Object> rowArray = new ArrayList<Object>(); // Cursor cursor; // try // // cursor = db.rawQuery("SELECT "+RECIPE_NAME+","+ IMAGE_PREVIEW+", "+ INGREDIENTS+","+ DIRECTIONS+" FROM"+TABLE_NAME+" ORDER BY RANDOM() LIMIT 1", null); // // cursor.moveToFirst(); // // if (!cursor.isAfterLast()) // do // rowArray.add(cursor.getString(0)); // rowArray.add(cursor.getString(1)); // rowArray.add(cursor.getString(2)); // rowArray.add(cursor.getString(3)); // // while (cursor.moveToNext()); // // // cursor.close(); // // catch (SQLException e) // // Log.e("DB ERROR", e.toString()); // e.printStackTrace(); // // // // return rowArray; //
/** this code is used to get data from database base on id value */
public ArrayList<Object> getDetail(long id)
ArrayList<Object> rowArray = new ArrayList<Object>();
Cursor cursor;
try
cursor = db.query(
TABLE_NAME,
new String[] RECIPE_NAME, IMAGE_PREVIEW, INGREDIENTS, DIRECTIONS,
ID + "=" + id,
null, null, null, null, null);
cursor.moveToFirst();
if (!cursor.isAfterLast())
do
rowArray.add(cursor.getString(0));
rowArray.add(cursor.getString(1));
rowArray.add(cursor.getString(2));
rowArray.add(cursor.getString(3));
while (cursor.moveToNext());
cursor.close();
catch (SQLException e)
Log.e("DB ERROR", e.toString());
e.printStackTrace();
return rowArray;
ListRecipesFragment 类:
package com.mypackage.example;
import android.content.Context;
import android.content.Intent;
import android.content.res.Configuration;
import android.database.SQLException;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.BaseAdapter;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;
import java.io.IOException;
import java.util.ArrayList;
/**
* A simple @link Fragment subclass.
*/
public class ListRecipesFragment extends Fragment
EditText edtSearch;
ListView listRecipes;
String RecipeNameKeyword = "";
static DBHelper dbhelper;
ArrayList<ArrayList<Object>> data;
ListAdapter la;
static int[] id;
static String[] RecipeName;
static String[] Preview;
static String[] CookTime;
/** This class is used to create custom listview */
static class ListAdapter extends BaseAdapter
private LayoutInflater inflater;
private Context ctx;
public ListAdapter(Context context)
inflater = LayoutInflater.from(context);
ctx = context;
public int getCount()
// TODO Auto-generated method stub
return RecipeName.length;
public Object getItem(int position)
// TODO Auto-generated method stub
return position;
public long getItemId(int position)
// TODO Auto-generated method stub
return position;
public View getView(int position, View convertView, ViewGroup parent)
// TODO Auto-generated method stub
ViewHolder holder;
if(convertView == null)
convertView = inflater.inflate(R.layout.row, null);
holder = new ViewHolder();
holder.txtRecipeName = (TextView) convertView.findViewById(R.id.txtRecipeName);
holder.txtReadyIn = (TextView) convertView.findViewById(R.id.txtReadyIn);
holder.imgPreview = (ImageView) convertView.findViewById(R.id.imgPreview);
convertView.setTag(holder);
else
holder = (ViewHolder) convertView.getTag();
holder.txtRecipeName.setText(RecipeName[position]);
int imagePreview = ctx.getResources().getIdentifier(Preview[position], "drawable", ctx.getPackageName());
holder.imgPreview.setImageResource(imagePreview);
return convertView;
static class ViewHolder
TextView txtRecipeName, txtReadyIn;
ImageView imgPreview;
public ListRecipesFragment()
// Required empty public constructor
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState)
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_list_recipes, container, false);
@Override
public void onViewCreated(View view, Bundle savedInstanceState)
super.onViewCreated(view, savedInstanceState);
dbhelper = new DBHelper(getView().getContext());
la = new ListAdapter(getView().getContext());
listRecipes = (ListView) getView().findViewById(R.id.listRecipes);
/**
* when this app's installed at the first time, code below will
* copy database stored in assets to
* /data/data/com.recipes.app/databases/
*/
try
dbhelper.createDataBase();
catch(IOException ioe)
throw new Error("Unable to create database");
/** then, the database will be open to use */
try
dbhelper.openDataBase();
catch(SQLException sqle)
throw sqle;
new getDataTask().execute();
listRecipes.setOnItemClickListener(new AdapterView.OnItemClickListener()
public void onItemClick(AdapterView<?> arg0, View arg1, int position,
long arg3)
// TODO Auto-generated method stub
/**
* when one of item in the list is clicked, this app will access
* RecipeDetail.class. it also send id value to that class
*/
Intent i = new Intent(getActivity(), RecipeDetailActivity.class);
i.putExtra("id_for_detail", id[position]);
startActivity(i);
);
/** this class is used to handle thread */
public class getDataTask extends AsyncTask<Void, Void, Void>
@Override
protected void onPreExecute()
// TODO Auto-generated method stub
@Override
protected Void doInBackground(Void... arg0)
// TODO Auto-generated method stub
getDataFromDatabase(RecipeNameKeyword);
return null;
@Override
protected void onPostExecute(Void result)
// TODO Auto-generated method stub
//prgLoading.setVisibility(8);
if(id.length > 0)
listRecipes.setVisibility(View.INVISIBLE);
listRecipes.setAdapter(la);
else
//txtAlert.setVisibility(0);
dbhelper.close();
/**
* this code is used to get data from database and store them
* to array attributes
*/
public void getDataFromDatabase(String RecipeNameKeyword)
data = dbhelper.getAllData(RecipeNameKeyword);
id = new int[data.size()];
RecipeName = new String[data.size()];
Preview = new String[data.size()];
for(int i=0;i<data.size();i++)
ArrayList<Object> row = data.get(i);
id[i] = Integer.parseInt(row.get(0).toString());
RecipeName[i] = row.get(1).toString();
Preview[i] = row.get(2).toString().trim();
@Override
public void onConfigurationChanged(final Configuration newConfig)
// Ignore orientation change to keep activity from restarting
super.onConfigurationChanged(newConfig);
【问题讨论】:
listRecipes.xml
与数据库路径和/或连接有什么关系?为什么将其包含在代码中。 row.xml
呢?仅共享可能与当前问题相关的代码。请查看How to create a Minimal, Reproducible Example。
更具体地说明错误:它用于哪一行代码?你做了什么来调试这个问题?仅仅说您找到了解决方案但它们没有奏效是不够的。什么“解决方案”,你尝试了什么?代码显示您将DB_PATH
输出到日志中,那么您是否检查了日志并确认路径正确?您是否真的去了路径并确认文件存在于您认为的位置?您还在多个地方调用了copydata()
函数,那么您是否跟踪了该代码并确保它正常工作?解决方案可能只是老式的调试。
【参考方案1】:
确保执行文件路径目录包含“cc_recipes.db”文件。
【讨论】:
它包含数据库文件以上是关于FileNotFoundException SQLite 数据库 Android的主要内容,如果未能解决你的问题,请参考以下文章
在 spark 中跳过 hive 表中丢失的文件以避免 FileNotFoundException
检测 java.io.FileNotFoundException 的根本原因