W / SQLite:(28)无法打开

时间:2018-12-07 19:21:08

标签: sqlite android-studio android-fragments android-recyclerview recycler-adapter

我是应用程序开发的新手,我正尝试创建一个简短的应用程序。

有一个选项卡视图,每个选项卡都打开了不同的片段,其中包含一个不同的recycler_view,该视图将由我在资产文件夹中放置的.sqlite文件中不同表的结果填充。

,但是我一直收到错误消息,说文件无法打开。

我不知道如何解决这个问题或显示什么可以帮助有更多经验的人发现错误,所以这就是一切。

RecyclerView适配器:

package com.dummies.finalproject.adapter;

public class AbbreviationsAdapter extends RecyclerView.Adapter<SetViewHolder> {
    private Activity activity;
    List<Item> items= Collections.emptyList();
    private OnTapListener onTapListener;

    public AbbreviationsAdapter(Activity activity,List<Item> items){
        this.activity=activity;
        this.items=items;
    }

    @NonNull
    @Override
    public SetViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int i) {
        View view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.custom_list_item,viewGroup, false);
        return new SetViewHolder(view);

    }

    @Override
    public void onBindViewHolder(@NonNull SetViewHolder setViewHolder, final int i) {
    setViewHolder.txt_phrase.setText(items.get(i).getPhrase());
    setViewHolder.txt_descrption.setText(items.get(i).getDescription());
    setViewHolder.itemView.setOnClickListener(v -> {
        if(onTapListener !=null){
            onTapListener.onTapView(i);
        }

    });
    }

    @Override
    public int getItemCount() {
        return items.size();

    }
    public void setOnTapListener(OnTapListener onTapListener){
        this.onTapListener=onTapListener;
    }
}

片段

    package com.dummies.finalproject.FragmentActivity;

import android.database.Cursor;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Toast;

import com.dummies.finalproject.DatabaseHelper;
import com.dummies.finalproject.Item.Item;
import com.dummies.finalproject.OnTapListener;
import com.dummies.finalproject.R;
import com.dummies.finalproject.adapter.AbbreviationsAdapter;

import java.util.ArrayList;

public class AbbreviationsFragment extends Fragment {
    private RecyclerView recyclerView;
    private DatabaseHelper databaseHelper;
    private ArrayList<com.dummies.finalproject.Item.Item> arrayList = new ArrayList<com.dummies.finalproject.Item.Item>();
    private Cursor cursor;
    private AbbreviationsAdapter adapter;
    public AbbreviationsFragment(){

    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    }

    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        View viewGroup = inflater.inflate(R.layout.list_item, container, false);
        recyclerView = viewGroup.findViewById(R.id.recyler_view);
        loadDatabase();
        return viewGroup;
    }
    public void loadDatabase(){
        databaseHelper= new DatabaseHelper(getActivity());
        databaseHelper.checkandcopydatabase();
        databaseHelper.openDatabase();
        cursor=databaseHelper.QueryData("SELECT * FROM ABBREVIATIONS");
        if(cursor !=null){
            if (cursor.moveToFirst()){
                do {
                    Item item = new Item();
                    item.setPhrase(cursor.getString(1));
                    item.setDescription(cursor.getString(2));
                    arrayList.add(item);
                }while (cursor.moveToNext());

            }
        }
        final LinearLayoutManager linearLayoutManager = new LinearLayoutManager(getContext());
        adapter= new AbbreviationsAdapter(getActivity(),arrayList);
        adapter.setOnTapListener(new OnTapListener() {
            @Override
            public void onTapView(int position) {
                Toast.makeText(getContext(),"Click to "+ position,Toast.LENGTH_SHORT).show();
            }
        });
        recyclerView.setHasFixedSize(true);
        recyclerView.setLayoutManager(linearLayoutManager);
        recyclerView.setAdapter(adapter);
    }
}

数据库帮助器

public class DatabaseHelper extends SQLiteOpenHelper {
    private static final String DBNAME ="DoYouGetMeDoc.sqlite";
    private static String DB_PATH ="";
    private final Context context;
    private SQLiteDatabase database;
    public DatabaseHelper(Context context){
        super(context,DBNAME,null,1);
        DB_PATH = context.getApplicationInfo().dataDir + "/databases";
        this.context = context; }
    @Override
    public void onCreate(SQLiteDatabase db) {}
    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {}
    public void checkandcopydatabase(){
        boolean dbExsist= checkdatabase();
        if(dbExsist){
            Log.d("Tag", "Database Exist");
        }else{
            this.getReadableDatabase();}
        try {
            copydatabase();
        } catch (IOException e) {
            e.printStackTrace();
            Log.d("TAG", "try again"); } }
    public boolean checkdatabase(){
        SQLiteDatabase checkDB=null;
        String myPath=DB_PATH + DBNAME;
        checkDB = SQLiteDatabase.openDatabase(myPath,null,SQLiteDatabase.OPEN_READWRITE);
        if(checkDB != null) {
            checkDB.close(); }
            return checkDB != null; }
    public void copydatabase() throws IOException {
        InputStream myput = context.getAssets().open(DBNAME);
        String outFileName = DB_PATH + DBNAME;
        OutputStream myOutput= new FileOutputStream(outFileName);
        byte[] buffer = new byte[1024];
        int length;
        while ((length=myput.read(buffer))>0){
            myOutput.write(buffer,0,length);}
        myOutput.flush();
        myOutput.close();
        myput.close();}
    public void openDatabase(){
        String myPath=DB_PATH+DBNAME;
        database=SQLiteDatabase.openDatabase(myPath,null,SQLiteDatabase.OPEN_READWRITE);}
    public synchronized void close(){
        if(database !=null){
            database.close(); }
        super.close(); }
    public Cursor QueryData(String query){
        return database.rawQuery(query,null);
    }}

堆栈跟踪:

E/SQLiteLog: (14) cannot open file at line 36170 of [8201f4e1c5]
    (14) os_unix.c:36170: (2) open(/data/user/0/com.dummies.finalproject/databasesDoYouGetMeDoc.sqlite) - 
E/SQLiteLog: (1) Process es.finalproject : Pid (20311) Uid (10189) Euid (10189) Gid (10189) Egid (10189)
    (1) osStat failed "/data/user/0/com.dummies.finalproject/databasesDoYouGetMeDoc.sqlite" due to error (2)
    (1) Stat of /data/user/0/com.dummies.finalproject : st_mode(40700) st_uid(10189) st_gid(10189) st_ino(75991)
    (1) Stat of /data/user/0 : st_mode(40771) st_uid(1000) st_gid(1000) st_ino(65537)
    (1) Stat of /data/user : st_mode(40711) st_uid(1000) st_gid(1000) st_ino(327686)
    (1) Stat of /data : st_mode(40771) st_uid(1000) st_gid(1000) st_ino(2)
E/SQLiteDatabase: Failed to open database '/data/user/0/com.dummies.finalproject/databasesDoYouGetMeDoc.sqlite'.
    android.database.sqlite.SQLiteCantOpenDatabaseException: unknown error (code 1294): Could not open database
    #################################################################
    Error Code : 1294 (SQLITE_CANTOPEN_ENOENT)
    Caused By : Specified directory or database file does not exist.
        (unknown error (code 1294): Could not open database)
    #################################################################

如果您能帮助我,我将非常感激。

更新:

我进行了以下更改:

String outFileName = DB_PATH + DBNAME;

String outFileName = DB_PATH + "/" + DBNAME;

,现在在堆栈跟踪中出现以下错误:

W/SQLiteLog: (28) failed to open "/data/user/0/com.dummies.finalproject/databases/DoYouGetMeDoc.sqlite" with flag (131074) and mode_t (0) due to error (2)
    (28) failed to open "/data/user/0/com.dummies.finalproject/databases/DoYouGetMeDoc.sqlite" with flag (131072) and mode_t (0) due to error (2)
E/SQLiteLog: (14) cannot open file at line 36170 of [8201f4e1c5]
    (14) os_unix.c:36170: (2) open(/data/user/0/com.dummies.finalproject/databases/DoYouGetMeDoc.sqlite) - 
    (1) Process es.finalproject : Pid (13594) Uid (10191) Euid (10191) Gid (10191) Egid (10191)
    (1) osStat failed "/data/user/0/com.dummies.finalproject/databases/DoYouGetMeDoc.sqlite" due to error (2)
    (1) osStat failed "/data/user/0/com.dummies.finalproject/databases" due to error (2)
    (1) Stat of /data/user/0/com.dummies.finalproject : st_mode(40700) st_uid(10191) st_gid(10191) st_ino(75790)
    (1) Stat of /data/user/0 : st_mode(40771) st_uid(1000) st_gid(1000) st_ino(65537)
    (1) Stat of /data/user : st_mode(40711) st_uid(1000) st_gid(1000) st_ino(327686)
    (1) Stat of /data : st_mode(40771) st_uid(1000) st_gid(1000) st_ino(2)
E/SQLiteDatabase: Failed to open database '/data/user/0/com.dummies.finalproject/databases/DoYouGetMeDoc.sqlite'.
    android.database.sqlite.SQLiteCantOpenDatabaseException: unknown error (code 1294): Could not open database
    #################################################################
    Error Code : 1294 (SQLITE_CANTOPEN_ENOENT)
    Caused By : Specified directory or database file does not exist.
        (unknown error (code 1294): Could not open database)
    #################################################################

1 个答案:

答案 0 :(得分:0)

您的第一个问题似乎是路径中缺少分隔符。

是在说

data/user/0/com.dummies.finalproject/databasesDoYouGetMeDoc.sqlite

应该是

data/user/0/com.dummies.finalproject/databases/DoYouGetMeDoc.sqlite'

所以尝试更改

String outFileName = DB_PATH + DBNAME;

String outFileName = DB_PATH + "/" + DBNAME;

您的第二个问题是,当数据库不存在时,您尝试按照以下步骤获取数据库(不存在):-

this.getReadableDatabase();

通常尝试在复制之前进行获取,然后打开数据库(然后覆盖空数据库),以尝试绕过不存在的数据库目录。

我建议进行一些更改。

  1. 使用上下文的getDatabase(the_database_name).getPath()方法以字符串形式返回完整的数据库路径。因此,只要the_database_name路径是正确的。
  2. 而不是使用SQliteDatabase openDatabase方法来查看数据库是否存在,只需检查文件本身是否存在,是否不存在,然后再检查父目录是否存在并且不创建目录。 / li>
  3. 在实例化数据库助手时进行检查并复制(如果需要)。

这样,您可能会发现以下版本的 DatabaseHelper.java 适用(经过测试):-

public class DatabaseHelper extends SQLiteOpenHelper {
    private static final String DBNAME ="DoYouGetMeDoc.sqlite";
    private static String DBPATH;
    private final Context context;
    private SQLiteDatabase database;
    public DatabaseHelper(Context context){
        super(context,DBNAME,null,1);
        DBPATH = context.getDatabasePath(DBNAME).getPath(); //<<<<<<<<<< ADDDED
        this.context = context;
        //<<<<<<<<<< START OF ADDED CODE >>>>>>>>>>
        if (!checkDBFile(DBPATH)) {
            try {
                copydatabase();
            } catch (IOException e) {
                e.printStackTrace();
                throw new RuntimeException("Error Copying Database");
            }
        }
        database = this.getWritableDatabase(); //OPEN THE Database
        //<<<<<<<<<< END Of ADDED CODE >>>>>>>>>>
    }
    @Override
    public void onCreate(SQLiteDatabase db) {}
    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {}

    /**
     * Alternantive DB check that checks if the file exists,
     * if not makes the database directory if that does not exist
     * @param dbpath
     * @return
     */
    private boolean checkDBFile(String dbpath) {
        File db = new File(dbpath);
        if (db.exists()) return true;
        File dbdir = new File(db.getParent());
        if (!dbdir.exists()) {
            dbdir.mkdirs();
        }
        return false;
    }

    public void copydatabase() throws IOException {
        InputStream myput = context.getAssets().open(DBNAME);
        String outFileName = DBPATH; //<<<<<<<<<< CHANGED
        OutputStream myOutput= new FileOutputStream(outFileName);
        byte[] buffer = new byte[1024];
        int length;
        while ((length=myput.read(buffer))>0){
            myOutput.write(buffer,0,length);}
        myOutput.flush();
        myOutput.close();
        myput.close();
    }

    public synchronized void close(){
        if(database !=null){
            database.close(); }
        super.close(); }
    public Cursor QueryData(String query){
        return database.rawQuery(query,null);
    }
}