W / SQLite: (28) не удалось открыть - PullRequest
0 голосов
/ 07 декабря 2018

Я новичок в разработке приложений, и я пытаюсь создать приложение, которое вкратце.

есть вкладка с каждой вкладкой, открывающая различный фрагмент, который будет содержать другой 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);
    }
}

DatabaseHelper :

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 голосов
/ 08 декабря 2018

Ваша первая проблема, кажется, отсутствует разделитель в пути.

То есть он говорит

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. использовать методы Context getDatabase(the_database_name).getPath(), чтобы вернуть полный путь к базе данных в виде строки.Таким образом, до тех пор, пока имя_базы_данных, путь будет правильным.
  2. , вместо того, чтобы использовать метод openDatabase SQliteDatabase, чтобы проверить, существует ли база данных, просто проверьте, существует ли сам файл, а если нет, то проверьте, еслиродительский каталог существует, и он не создает каталоги.
  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);
    }
}
...