sqlite 无法打印带有SQL数据库语句的生成列表[Android Studio]

mnowg1ta  于 2023-01-13  发布在  SQLite
关注(0)|答案(1)|浏览(115)

我编写了一些代码,连接到设备内部存储器中的数据库,运行SQL语句以过滤摘录,然后迭代结果并创建一个列表,该列表可以在程序中稍后使用。但是,当使用日志语句检查时,该列表不会返回任何内容。我在迭代之前检查了SQL语句是否与日志语句一起工作,并且它返回了正确的行值。

package com.example.fit_world;

import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;

import android.content.res.AssetManager;
import android.database.Cursor;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import android.os.Bundle;
import android.util.Log;

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 java.util.List;

import com.example.fit_world.Exercise;

public class GenerateWorkout extends AppCompatActivity {
    private static final String DATABASE_NAME = "Exercises.db";
    private SQLiteDatabase database;

    private void copyDatabaseToInternalStorage() {
        InputStream inputStream = null;
        OutputStream outputStream = null;
        try {
            // Open the database file in the assets folder
            AssetManager assetManager = getAssets();
            inputStream = assetManager.open(DATABASE_NAME);
            if (inputStream == null) {
                throw new IOException("Failed to open file: " + DATABASE_NAME);
            }

            // Generate a unique file name for the database in the internal storage
            File outputFile = new File(getFilesDir(), "Exercises_" + System.currentTimeMillis() + ".db");

            // Check if the file already exists in the internal storage
            if (outputFile.exists()) {
                // Delete the file if it already exists
                outputFile.delete();
            }

            outputStream = new FileOutputStream(outputFile);

            // Copy the database file from the assets folder to the internal storage
            byte[] buffer = new byte[1024];
            int length;
            while ((length = inputStream.read(buffer)) > 0) {
                outputStream.write(buffer, 0, length);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            // Close the streams
            try {
                if (inputStream != null) {
                    inputStream.close();
                }
                if (outputStream != null) {
                    outputStream.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_generate_workout);
        String equipmentType = "None";
        String difficultyType = "Easy";
        String weightGoalType = "Weight Loss";

        List<Exercise> exercises = getExercisesFromDatabase(equipmentType, difficultyType, weightGoalType);
        for (Exercise exercise : exercises) {
            Log.d("LOL", exercise.toString());
        }
    }

    private List<Exercise> getExercisesFromDatabase(String equipmentType, String difficultyType, String weightGoalType) {
        List<Exercise> exercises = new ArrayList<>();
        // Check if the database file exists in the internal storage
        File databaseFile = new File(getFilesDir(), DATABASE_NAME);
        if (!databaseFile.exists()) {
            // If the database file does not exist, copy it from the assets folder
            copyDatabaseToInternalStorage();
        }

            // Open the database file in the internal storage
            SQLiteDatabase database = null;
            Cursor cursor = null;
            try {
                // Open the database file in the internal storage
                database = openOrCreateDatabase("Exercises.db", MODE_PRIVATE, null);

                // Execute the query to retrieve the list of exercises
                String query = "SELECT * FROM Exercises WHERE Equipment = ? AND Difficulty = ? AND Goal = ?";
                String[] selectionArgs = new String[]{equipmentType, difficultyType, weightGoalType};
                cursor = database.rawQuery(query, selectionArgs);
                int rowCount = cursor.getCount();
                System.out.print(rowCount);
                Log.d("TAG", "Row count: " + rowCount);
                Log.d("MMM", "Row count: " + database.rawQuery("SELECT * FROM exercises", null).getCount());


                // Iterate through the result set and create a list of exercises
                while (cursor.moveToNext()) {
                    int idColumnIndex = cursor.getColumnIndex("id");
                    int nameColumnIndex = cursor.getColumnIndex("name");
                    int descriptionColumnIndex = cursor.getColumnIndex("description");
                    int equipmentColumnIndex = cursor.getColumnIndex("equipment");
                    int difficultyColumnIndex = cursor.getColumnIndex("difficulty");
                    int weightGoalColumnIndex = cursor.getColumnIndex("weight_goal");
                    int requiredEquipmentColumnIndex = cursor.getColumnIndex("required_equipment");
                    int numberOfRepsColumnIndex = cursor.getColumnIndex("number_of_reps");
                    if (idColumnIndex != -1 && nameColumnIndex != -1 && descriptionColumnIndex != -1 && equipmentColumnIndex != -1 &&
                            difficultyColumnIndex != -1 && weightGoalColumnIndex != -1 && requiredEquipmentColumnIndex != -1 &&
                            numberOfRepsColumnIndex != -1) {
                        int id = cursor.getInt(idColumnIndex);
                        String name = cursor.getString(nameColumnIndex);
                        String description = cursor.getString(descriptionColumnIndex);
                        String equipment = cursor.getString(equipmentColumnIndex);
                        String difficulty = cursor.getString(difficultyColumnIndex);
                        String weightGoal = cursor.getString(weightGoalColumnIndex);
                        String requiredEquipment = cursor.getString(requiredEquipmentColumnIndex);
                        int numberOfReps = cursor.getInt(numberOfRepsColumnIndex);
                        Exercise exercise = new Exercise(id, name, description, equipment, difficulty, weightGoal, requiredEquipment, numberOfReps);
                        exercises.add(exercise);

                        Log.d("TAG", "Exercise name: " + name);
                        Log.d("TAG", "Exercise description: " + description);
                        Log.d("TAG", "Exercise equipment: " + equipment);
                        Log.d("TAG", "Number of exercises retrieved: " + exercises.size());

                    }
                }
            } catch (SQLException e) {
                e.printStackTrace();
                Log.e("TAG", "Error accessing database: " + e.getMessage());
            } finally {
            // Close the cursor and database
            if (cursor != null) {
                cursor.close();
            }
            if (database != null) {
                database.close();
            }
        }
        return exercises;

        }
    }

我尝试使用日志语句来查看打印的摘录列表,但是没有任何内容打印到logcat,SQL语句的工作方式与我使用日志语句查看打印的值相同,并且工作正常

3wabscal

3wabscal1#

我猜想,当有效数据存在时,确实会打印出一些东西,但不是预期的,因此可能会错过。
更具体地说,打印的内容取决于Exercise类的toString方法,该方法用于:-

for (Exercise exercise : exercises) {
        Log.d("LOL", exercise.toString());
    }

它可能是D/LOL: a.a.so75035530javasqliteemptylist.Exercise@58c3a3e(这是对您提供的代码的改编)
除此之外,核心代码看起来很好。以下是adaptated代码,用于测试打开的数据库中的一些数据(单行)(只有一行):-

private List<Exercise> getExercisesFromDatabase(String equipmentType, String difficultyType, String weightGoalType) {
    List<Exercise> exercises = new ArrayList<>();
    // Check if the database file exists in the internal storage
    /*
    File databaseFile = new File(getFilesDir(), DATABASE_NAME);
    if (!databaseFile.exists()) {
        // If the database file does not exist, copy it from the assets folder
        copyDatabaseToInternalStorage();
    }

     */

    // Open the database file in the internal storage
    SQLiteDatabase database = null;
    Cursor cursor = null;
    try {
        // Open the database file in the internal storage
        //database = openOrCreateDatabase("Exercises.db", MODE_PRIVATE, null);
        File dbfile = this.getDatabasePath(DATABASE_NAME);
        database = SQLiteDatabase.openOrCreateDatabase(dbfile,null);

        // Execute the query to retrieve the list of exercises
        String query = "SELECT * FROM Exercises /*WHERE Equipment = ? AND Difficulty = ? AND weightGoal = ?*/";
        String[] selectionArgs = new String[]{equipmentType, difficultyType, weightGoalType};
        cursor = database.rawQuery(query, /*selectionArgs*/ new String[]{});
        DatabaseUtils.dumpCursor(cursor);
        int rowCount = cursor.getCount();
        System.out.print(rowCount);
        Log.d("TAG", "Row count: " + rowCount);
        Log.d("MMM", "Row count: " + database.rawQuery("SELECT * FROM exercises", null).getCount());

        // Iterate through the result set and create a list of exercises
        while (cursor.moveToNext()) {
            int idColumnIndex = cursor.getColumnIndex("id");
            int nameColumnIndex = cursor.getColumnIndex("name");
            int descriptionColumnIndex = cursor.getColumnIndex("description");
            int equipmentColumnIndex = cursor.getColumnIndex("equipment");
            int difficultyColumnIndex = cursor.getColumnIndex("difficulty");
            int weightGoalColumnIndex = cursor.getColumnIndex("weightGoal");
            int requiredEquipmentColumnIndex = cursor.getColumnIndex("requiredEquipment");
            int numberOfRepsColumnIndex = cursor.getColumnIndex("numberOfReps");
            if (1 == 1 /*idColumnIndex != -1 && nameColumnIndex != -1 && descriptionColumnIndex != -1 && equipmentColumnIndex != -1 &&
                    difficultyColumnIndex != -1 && weightGoalColumnIndex != -1 && requiredEquipmentColumnIndex != -1 &&
                    numberOfRepsColumnIndex != -1*/) {
                int id = cursor.getInt(idColumnIndex);
                String name = cursor.getString(nameColumnIndex);
                String description = cursor.getString(descriptionColumnIndex);
                String equipment = cursor.getString(equipmentColumnIndex);
                String difficulty = cursor.getString(difficultyColumnIndex);
                String weightGoal = cursor.getString(weightGoalColumnIndex);
                String requiredEquipment = cursor.getString(requiredEquipmentColumnIndex);
                int numberOfReps = cursor.getInt(numberOfRepsColumnIndex);
                Exercise exercise = new Exercise(id, name, description, equipment, difficulty, weightGoal, requiredEquipment, numberOfReps);
                exercises.add(exercise);

                Log.d("TAG", "Exercise name: " + name);
                Log.d("TAG", "Exercise description: " + description);
                Log.d("TAG", "Exercise equipment: " + equipment);
                Log.d("TAG", "Number of exercises retrieved: " + exercises.size());

            }
        }
    } catch (SQLException e) {
        e.printStackTrace();
        Log.e("TAG", "Error accessing database: " + e.getMessage());
    } finally {
        // Close the cursor and database
        if (cursor != null) {
            cursor.close();
        }
        if (database != null) {
            database.close();
        }
    }
    return exercises;

}
  • 如图所示,数据库位于标准位置,而不是使用资产等进行测试,它是在初始(MainActivity)中创建和填充的,初始(MainActivity)为:-

公共类MainActivity扩展了AppCompatActivity {

@Override
  protected void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      setContentView(R.layout.activity_main);
      Intent intent = new Intent(this,GenerateWorkout.class);
      frigDatabase();
      startActivity(intent);
  }

  void frigDatabase() {
      SQLiteDatabase db;
      String dbname = GenerateWorkout.DATABASE_NAME;
      File dbfile = this.getDatabasePath(dbname);
      boolean exists = dbfile.exists();
       db = SQLiteDatabase.openOrCreateDatabase(dbfile,null);
      if (!exists) {
          db.execSQL("CREATE TABLE exercises (" +
                  "id INTEGER PRIMARY KEY," +
                  "name TEXT," +
                  "description TEXT," +
                  "equipment TEXT," +
                  "difficulty TEXT," +
                  "weightGoal TEXT," +
                  "requiredEquipment TEXT," +
                  "numberOfReps INTEGER DEFAULT 10" +
                  ");"
          );
          ContentValues cv = new ContentValues();
          cv.put("name","fred");
          cv.put("description","d1");
          cv.put("equipment","E1");
          cv.put("difficulty","hard");
          cv.put("weightGoal","10kg");
          cv.put("requiredEquipment","ALL");
          db.insert("exercises",null,cv);
      }

  }

}

  • 所做的其他更改是选择唯一一行(并使用基于Exercise类的列名(注意getColumnIndex是大小写相关的))。
  • 您还可能注意到,将DatabaseUtilsdumpCursor方法与此一起使用,则用于测试的结果输出为

:-

2023-01-07 09:34:55.792 I/System.out: >>>>> Dumping cursor android.database.sqlite.SQLiteCursor@67e09f
2023-01-07 09:34:55.792 I/System.out: 0 {
2023-01-07 09:34:55.793 I/System.out:    id=1
2023-01-07 09:34:55.793 I/System.out:    name=fred
2023-01-07 09:34:55.793 I/System.out:    description=d1
2023-01-07 09:34:55.793 I/System.out:    equipment=E1
2023-01-07 09:34:55.793 I/System.out:    difficulty=hard
2023-01-07 09:34:55.793 I/System.out:    weightGoal=10kg
2023-01-07 09:34:55.793 I/System.out:    requiredEquipment=ALL
2023-01-07 09:34:55.793 I/System.out:    numberOfReps=10
2023-01-07 09:34:55.793 I/System.out: }
2023-01-07 09:34:55.793 I/System.out: <<<<<
2023-01-07 09:34:55.793 D/TAG: Row count: 1
2023-01-07 09:34:55.794 D/MMM: Row count: 1
2023-01-07 09:34:55.795 D/TAG: Exercise name: fred
2023-01-07 09:34:55.795 D/TAG: Exercise description: d1
2023-01-07 09:34:55.795 D/TAG: Exercise equipment: E1
2023-01-07 09:34:55.795 D/TAG: Number of exercises retrieved: 1

2023-01-07 09:34:55.802 D/LOL: a.a.so75035530javasqliteemptylist.Exercise@ca545ec

正如您所看到的,输出/结果与预期一致,但是最后一行是通过返回的List从循环中获得的,因此可能不是预期的结果。
但是,如果使用以下内容:-

List<Exercise> exercises = getExercisesFromDatabase(equipmentType, difficultyType, weightGoalType);
    for (Exercise exercise : exercises) {
        Log.d("LOL", exercise.toString());
        Log.d("LOL_","Name  is " + exercise.name + " Description is " + exercise.description + " etc."); /*<<<<<<<<<< ADDED >>>>>>>>>>*/ 
    }

那么输出将更容易识别:

2023-01-07 09:51:07.442 D/LOL: a.a.so75035530javasqliteemptylist.Exercise@ca545ec
2023-01-07 09:51:07.442 D/LOL_: Name  is fred Description is d1 etc.
    • 其他**

正如您所说的,dumpCursor确实提取了预期的数据,那么最可能的问题是,至少有一个??columnIndex索引值正在查找游标中没有的列,因此为-1,因此将不满足**if**语句(if (idColumnIndex != -1 && nameColumnIndex != ....(检查dumpCursor输出是否告诉您实际的列名)

  • if的主体中首次尝试从游标获取值时添加断点(请注意,IF子句已更改为始终为true,以允许debug进入主体) 并在调试模式下运行。这将允许您查看内容。以下是显示断点的示例(通过点击行号放置红点)和在调试模式下运行应用程序的结果(Shift F9):-

  • 可以确定weightGaolIndex是**-1**,因此列名,根据行int weightGoalColumnIndex = cursor.getColumnIndex("Goal");*(注意Goal专门用于产生-1(*。使用调试扩展光标,然后扩展mColumnNameMap显示:-

  • 即光标中的列名为weigthGoalNOTGoal
  • 您还应该注意,**getColumnIndex**方法区分大小写,因此要搜索的名称的大小写必须与游标中列的大小写匹配。

相关问题