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

JDBC

dididaikeJdbcUtil备份

检测 java.io.FileNotFoundException 的根本原因

IntelliJ“FileNotFoundException”,文件存在

如何解决 System.IO.FileNotFoundException?