首页 > 解决方案 > FileNotFoundException SQLite 数据库 Android

问题描述

我正在尝试从现有的 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);
    }
}

标签: androidsqliteandroid-studioandroid-listview

解决方案


确保执行文件路径目录包含“cc_recipes.db”文件。


推荐阅读