我的数据库是newtable,表名是First。列是Name和Id。 当我的数据库和表名相同时,我可以访问数据库,但当我有另一个具有不同名称的表时,我无法访问它。 我只想在我的数据库中显示id为1的名称。 当我在手机中执行它时,它显示应用程序一直停止。
这是我的MainActivity.java
public class MainActivity extends AppCompatActivity {
SQLiteDatabase db;
Random rand=new Random();
int a=1;
String selectQuery="select Name from First where Id="+a+";"; //Cursor c = db.rawQuery(selectQuery,null);//????????
Cursor c;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (!CopyDBFromAssets.createDataBase(this, DB_NAME)) {
// handle unable to create/copy DB here
} else {
Log.d("MAINDBCOPY", "DB copied from assets.");
}
((Button) findViewById(R.id.button01)).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
DatabaseHelper myDbHelper = new DatabaseHelper(MainActivity.this);
db = myDbHelper.getWritableDatabase();
Cursor c = db.rawQuery(selectQuery,null);
Toast.makeText(MainActivity.this, "Successfully Imported", Toast.LENGTH_SHORT).show();
if (c.moveToFirst()) {
do {
TextView tvt=(TextView)findViewById(R.id.newtext);
String s=c.getString(0);
tvt.setText(s);
} while (c.moveToNext());
}
}
});
}
}
这是我的DatabaseHelper类文件
public class DatabaseHelper extends SQLiteOpenHelper {
String DB_PATH = null;
public static final String DB_NAME = "newtable.db";
private SQLiteDatabase myDataBase;
private final Context myContext;
public DatabaseHelper(Context context) {
super(context, DB_NAME, null, 10);
this.myContext = context;
this.DB_PATH = "/data/data/" + context.getPackageName() + "/" + "databases/";
Log.e("Path 1", DB_PATH);
}
@Override
public void onCreate(SQLiteDatabase db) {
Log.d("DBHELPER","onCreate Invoked");
}
@Override //<<<<<<<<
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
if (newVersion > oldVersion) {
/*
try {
copyDataBase();
} catch (IOException e) {
e.printStackTrace();
}
*/
}
}
public Cursor query(String table, String[] columns, String selection, String[] selectionArgs, String groupBy, String having, String orderBy) {
return myDataBase.query("First", null, null, null, null, null, null);
}
}
这是CopyDBFromAssests 公共类CopyDBFromAssets {
boolean copied = false;
public static boolean createDataBase(Context context, String databasename) {
boolean copied = false;
boolean dbExist = checkDataBase(context, databasename);
if(!dbExist) {
// calling this method will create an empty database
// which will hopefully be overidden, if not then
// empty database will exist ?????????
//this.getReadableDatabase(); <<<<< NOTE Commented out as empty db with no tables is useless
if (!checkAssetExists(context, databasename, "")) {
Log.e("CREATEDB", "Error getting asset " + databasename);
} else {
return copyDataBase(context, databasename);
}
return false;
}
return true;
}
private static boolean checkAssetExists(Context context, String assetfile, String path) {
boolean rv = false; // assume asset file doesn't exist
String[] assetsfound = new String[]{};
// Get the list of assets at the given path
try {
assetsfound = context.getAssets().list(path);
} catch (IOException e) {
Log.e("CHECKASSET","IO Exception when checking for the asset file." + e.getMessage());
return false;
}
// Check to see if the desired asset (passed assetfile) exists
for (String s: assetsfound) {
if (s.equals(assetfile)) {
rv = true;
break;
}
}
if (rv) {
Log.d("CHECKASSET", "Asset " + assetfile + " was found.");
} else {
String assetlist = "";
for (String s: assetsfound) {
assetlist = assetlist + " " + s;
}
Log.e("CHECKASSET", "Asset " + assetfile +
"could not be found. Assets that exists are:- " +
assetlist
);
}
// Asset not found lets try ignoring case
if (!rv) {
for (String s: assetsfound) {
if ((s.toLowerCase()).equals(assetfile.toLowerCase())) {
Log.e("CHECKASSET","Found asset as " + assetfile +
" but looking for " + s +
", although they are similar the case is different."
);
}
}
}
return rv;
}
这是堆栈跟踪。
11-16 17:38:07.551 32220-32220/com.example.darshil.dbchecking E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.darshil.dbchecking, PID: 32220
android.database.sqlite.SQLiteException: no such table: First (code 1): , while compiling: select Name from First where Id=1;
at android.database.sqlite.SQLiteConnection.nativePrepareStatement(Native Method)
at android.database.sqlite.SQLiteConnection.acquirePreparedStatement(SQLiteConnection.java:889)
at android.database.sqlite.SQLiteConnection.prepare(SQLiteConnection.java:500)
at android.database.sqlite.SQLiteSession.prepare(SQLiteSession.java:588)
at android.database.sqlite.SQLiteProgram.<init>(SQLiteProgram.java:58)
at android.database.sqlite.SQLiteQuery.<init>(SQLiteQuery.java:37)
at android.database.sqlite.SQLiteDirectCursorDriver.query(SQLiteDirectCursorDriver.java:44)
at android.database.sqlite.SQLiteDatabase.rawQueryWithFactory(SQLiteDatabase.java:1318)
at android.database.sqlite.SQLiteDatabase.rawQuery(SQLiteDatabase.java:1257)
at com.example.darshil.dbchecking.MainActivity$1.onClick(MainActivity.java:40)
at android.view.View.performClick(View.java:5612)
at android.view.View$PerformClick.run(View.java:22285)
at android.os.Handler.handleCallback(Handler.java:751)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:6123)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:867)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:757)
11-16 17:38:07.553 1601-5060/? W/ActivityManager: Force finishing activity com.example.darshil.dbchecking/.MainActivity
11-16 17:38:07.572 1601-1626/? E/ActivityManager: Sending non-protected broadcast com.motorola.motocare.INTENT_TRIGGER from system
4246:com.motorola.process.system/1000 pkg com.motorola.motgeofencesvc
java.lang.Throwable
at com.android.server.am.ActivityManagerService.broadcastIntentLocked(ActivityManagerService.java:18226)
at com.android.server.am.ActivityManagerService.broadcastIntent(ActivityManagerService.java:18826)
at android.app.ActivityManagerNative.onTransact(ActivityManagerNative.java:512)
at com.android.server.am.ActivityManagerService.onTransact(ActivityManagerService.java:2906)
at android.os.Binder.execTransact(Binder.java:565)
java.lang.Throwable
at com.android.server.am.ActivityManagerService.broadcastIntentLocked(ActivityManagerService.java:18226)
at com.android.server.am.ActivityManagerService.broadcastIntent(ActivityManagerService.java:18826)
at android.app.ActivityManagerNative.onTransact(ActivityManagerNative.java:512)
at com.android.server.am.ActivityManagerService.onTransact(ActivityManagerService.java:2906)
at android.os.Binder.execTransact(Binder.java:565)
答案 0 :(得分:1)
有很多问题,例如
使用以下行: -
SQLiteDatabase db = SQLiteDatabase.openDatabase("/data/data/com.package.name/databases/dbname.db", null, SQLiteDatabase.OPEN_READWRITE);
Cursor c = db.rawQuery(selectQuery,null);
尝试使用DBHelper复制数据库文件,这将创建一个数据库。
以下是这些问题的解决方案,当newtable.db
中存在名为 PATH_TO_YOUR_PROJECT\YOURPACKAGE\app\src\main\assets
的文件时: -
该解决方案包含了一个我称为CopyDbFromAssets
的新类,MainActivity
中的一些额外行。还有一些注释掉的行是多余的,或者会导致MainActivity.java
和DatabaseHelper.java
public class CopyDBFromAssets {
boolean copied = false;
public static boolean createDataBase(Context context, String databasename) {
boolean copied = false;
boolean dbExist = checkDataBase(context, databasename);
if(!dbExist) {
// calling this method will create an empty database
// which will hopefully be overidden, if not then
// empty database will exist ?????????
//this.getReadableDatabase(); <<<<< NOTE Commented out as empty db with no tables is useless
if (!checkAssetExists(context, databasename, "")) {
Log.e("CREATEDB", "Error getting asset " + databasename);
} else {
return copyDataBase(context, databasename);
}
return false;
}
return true;
}
private static boolean checkAssetExists(Context context, String assetfile, String path) {
boolean rv = false; // assume asset file doesn't exist
String[] assetsfound = new String[]{};
// Get the list of assets at the given path
try {
assetsfound = context.getAssets().list(path);
} catch (IOException e) {
Log.e("CHECKASSET","IO Exception when checking for the asset file." + e.getMessage());
return false;
}
// Check to see if the desired asset (passed assetfile) exists
for (String s: assetsfound) {
if (s.equals(assetfile)) {
rv = true;
break;
}
}
if (rv) {
Log.d("CHECKASSET", "Asset " + assetfile + " was found.");
} else {
String assetlist = "";
for (String s: assetsfound) {
assetlist = assetlist + " " + s;
}
Log.e("CHECKASSET", "Asset " + assetfile +
"could not be found. Assets that exists are:- " +
assetlist
);
}
// Asset not found lets try ignoring case
if (!rv) {
for (String s: assetsfound) {
if ((s.toLowerCase()).equals(assetfile.toLowerCase())) {
Log.e("CHECKASSET","Found asset as " + assetfile +
" but looking for " + s +
", although they are similar the case is different."
);
}
}
}
return rv;
}
// check if database exists to avoid recopying it
private static boolean checkDataBase (Context context, String database){
SQLiteDatabase checkDB = null;
String dbpath = context.getDatabasePath(database).getPath();
File dbFile = context.getDatabasePath(dbpath);
return dbFile.exists();
}
// copies db from local assets file, were it can be accessed and handled
private static boolean copyDataBase(Context context, String databasename) {
InputStream asset;
OutputStream db;
int bytescopied = 0;
int length_read;
int buffersize = 16384;
int blockcount = 0;
boolean rv = false;
try {
asset = context.getAssets().open(databasename);
} catch (IOException e) {
Log.e("COPYDB",
"IO Error opening the asset " +
databasename +
". Error Message was " +
e.getMessage()
);
return false;
}
try {
File databasesdir = new File(context.getDatabasePath(databasename).getParent());
databasesdir.mkdir();
db = new FileOutputStream(context.getDatabasePath(databasename).getPath());
} catch (IOException e) {
Log.e("COPYDB",
"IO Error opening the output file for the database with path " +
databasename +
". error Message was " +
e.getMessage()
);
e.printStackTrace();
try {
asset.close();
} catch (IOException e2) {
Log.e("COPYDB",
"IO Error closing the asset. Message was " + e2.getMessage()
);
}
return false;
}
byte[] buffer = new byte[buffersize];
try {
while ((length_read = asset.read(buffer)) > 0) {
db.write(buffer);
bytescopied = bytescopied + length_read;
blockcount++;
rv = true;
}
} catch (IOException e) {
Log.e("COPYDB",
"IO Error Copying Database. Bytes Copied = "
+ bytescopied +
" in " +
blockcount +
" blocks of " +
buffersize
);
}
Log.d("COPYDB","Succesfully copied Database " + databasename + " from the assets." +
" Number of bytes copied = " + bytescopied +
" in " + blockcount + " blocks of length " + buffersize
);
try {
db.flush();
db.close();
asset.close();
} catch (IOException e) {
Log.e("COPYDB",
"IO Error flushing or closing Database or closing asset."
);
}
return rv;
}
}
请注意!这包括非常广泛的日志记录,应该在发布App之前将其删除。
public class MainActivity extends AppCompatActivity {
SQLiteDatabase db;
//SQLiteDatabase db = SQLiteDatabase.openDatabase("/data/data/com.package.name/databases/dbname.db", null, SQLiteDatabase.OPEN_READWRITE);//????????
int a=1;
String selectQuery="select Name from newtable where Id="+a+";";
//Cursor c = db.rawQuery(selectQuery,null);//????????
Cursor c;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main2);
if (!CopyDBFromAssets.createDataBase(this, DB_NAME)) {
// handle unable to create/copy DB here
} else {
Log.d("MAINDBCOPY", "DB copied from assets.");
}
((Button) findViewById(R.id.button01)).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
DatabaseHelper myDbHelper = new DatabaseHelper(MainActivity.this);
db = myDbHelper.getWritableDatabase();
/*
try {
myDbHelper.createDataBase();
} catch (IOException ioe) {
throw new Error("Unable to create database");
}
try {
myDbHelper.openDataBase();
} catch (SQLException sqle) {
throw sqle;
}
*/
Cursor c = db.rawQuery(selectQuery,null);
Toast.makeText(MainActivity.this, "Successfully Imported", Toast.LENGTH_SHORT).show();
if (c.moveToFirst()) {
do {
TextView tvt=(TextView)findViewById(R.id.newtext);
String s=c.getString(0);
tvt.setText(s);
} while (c.moveToNext());
}
}
});
}
}
public class DatabaseHelper extends SQLiteOpenHelper {
String DB_PATH = null;
public static final String DB_NAME = "newtable.db";
private SQLiteDatabase myDataBase;
private final Context myContext;
public DatabaseHelper(Context context) {
super(context, DB_NAME, null, 10);
this.myContext = context;
this.DB_PATH = "/data/data/" + context.getPackageName() + "/" + "databases/";
Log.e("Path 1", DB_PATH);
}
/*
public void createDataBase() throws IOException {
boolean dbExist = checkDataBase();
if (dbExist) {
} else {
this.getReadableDatabase();
try {
copyDataBase();
} catch (IOException e) {
throw new Error("Error copying database");
}
}
}
*/
/*
private boolean checkDataBase() {
SQLiteDatabase checkDB = null;
try {
String myPath = DB_PATH + DB_NAME;
checkDB = SQLiteDatabase.openDatabase(myPath, null, SQLiteDatabase.OPEN_READONLY);
} catch (SQLiteException e) {
}
if (checkDB != null) {
checkDB.close();
}
return checkDB != null ? true : false;
}
*/
/*
private void copyDataBase() throws IOException {
InputStream myInput = myContext.getAssets().open(DB_NAME);
String outFileName = DB_PATH + DB_NAME;
OutputStream myOutput = new FileOutputStream(outFileName);
byte[] buffer = new byte[10];
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;
myDataBase = SQLiteDatabase.openDatabase(myPath, null, SQLiteDatabase.OPEN_READONLY);
}
*/
/*
@Override
public synchronized void close() {
if (myDataBase != null)
myDataBase.close();
super.close();
}
*/
@Override
public void onCreate(SQLiteDatabase db) {
Log.d("DBHELPER","onCreate Invoked");
}
@Override //<<<<<<<<
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
if (newVersion > oldVersion) {
/*
try {
copyDataBase();
} catch (IOException e) {
e.printStackTrace();
}
*/
}
}
public Cursor query(String table, String[] columns, String selection, String[] selectionArgs, String groupBy, String having, String orderBy) {
return myDataBase.query("newtable", null, null, null, null, null, null);
}
}
首次运行上述内容应导致: -
包含类似于以下内容的日志: -
11-12 16:39:58.503 5289-5289/mjt.myapplication D/CHECKASSET: Asset newtable.db was found.
11-12 16:39:58.504 5289-5289/mjt.myapplication D/COPYDB: Succesfully copied Database newtable.db from the assets. Number of bytes copied = 65536 in 4 blocks of length 16384
11-12 16:39:58.504 5289-5289/mjt.myapplication D/MAINDBCOPY: DB copied from assets.
这些应该将以下内容输出到日志中: -
11-12 16:50:17.365 5394-5394/? D/MAINDBCOPY: DB copied from assets.
将产生以下输出或类似结果: -
11-12 16:56:47.313 5631-5631/mjt.myapplication E/CHECKASSET: Asset newtable.dbcould not be found. Assets that exists are:- images sounds webkit
11-12 16:56:47.313 5631-5631/mjt.myapplication E/CREATEDB: Error getting asset newtable.db
我已经更新了这个问题。希望你能帮帮我
问题由android.database.sqlite.SQLiteException: no such table: First (code 1): , while compiling: select Name from First where Id=1;
即。数据库中没有名为 First 的表。
行String selectQuery="select Name from First where Id="+a+";";
定义表名,即从第一个 ....中选择名称。
这一行由Cursor c = db.rawQuery(selectQuery,null);
行调用
根据堆栈跟踪线: -
at com.example.darshil.dbchecking.MainActivity$1.onClick(MainActivity.java:40)
出于某种原因,假设数据库已成功复制,即日志包含以下行: -
D/MAINDBCOPY: DB copied from assets.
然后数据库的结构不包括名为 First 的表。
我建议您执行以下操作以确定哪些表存在以及表中包含哪些列(如果有): -
/**
* Log Database table Information
*/
public void logDatabaseTableInformation() {
final String LOGTAG = "DBINFO";
SQLiteDatabase db = this.getWritableDatabase();
Log.d(LOGTAG,new Object(){}.getClass().getEnclosingMethod().getName() + " initiated.");
String mastertable = "sqlite_master";
String typecolumn = "type";
String namecolumn = "name";
String sqlcolumn = "sql";
String[] args = new String[]{"table","android_metadata"};
Cursor csr = db.query(mastertable,
null,
typecolumn + "=? AND " + namecolumn + "!=?",
args,
null,null,null
);
while (csr.moveToNext()) {
Log.d(LOGTAG,"Database contains Table " +
csr.getString(csr.getColumnIndex(namecolumn)) +
" created by SQL " +
csr.getString(csr.getColumnIndex(sqlcolumn))
);
logTableInformation(csr.getString(csr.getColumnIndex(namecolumn)));
}
csr.close();
Log.d(LOGTAG,new Object(){}.getClass().getEnclosingMethod().getName() + " completed.");
}
private void logTableInformation(String table) {
final String LOGTAG = "DBINFO";
SQLiteDatabase db = this.getWritableDatabase();
Cursor csr = db.query(table,null,null,null,null,null,null);
Log.d(LOGTAG,"Table is " + table +
" Column Count = " + Integer.toString(csr.getColumnCount()) +
" Row Count = " + Long.toString(DatabaseUtils.queryNumEntries(db,table))
);
StringBuilder columns_as_string = new StringBuilder();
for (String s: csr.getColumnNames()) {
columns_as_string.append(s + " ");
}
Log.d(LOGTAG, "\tColumns are :- " + columns_as_string);
csr.close();
}
myDbHelper.logDatabaseTableInformation();
DatabaseHelper myDbHelper = new DatabaseHelper(MainActivity.this);
请注意,您仍会收到错误,但日志应包含以下内容的额外信息: -
11-17 06:55:26.386 2596-2596/mjt.myapplication D/CHECKASSET: Asset newtable.db was found.
11-17 06:55:26.386 2596-2596/mjt.myapplication D/COPYDB: Succesfully copied Database newtable.db from the assets. Number of bytes copied = 65536 in 4 blocks of length 16384
11-17 06:55:26.386 2596-2596/mjt.myapplication D/MAINDBCOPY: DB copied from assets.
...
11-17 06:55:39.487 2596-2596/mjt.myapplication D/DBHELPER: onCreate Invoked
11-17 06:55:39.491 2596-2596/mjt.myapplication D/DBINFO: logDatabaseTableInformation initiated.
11-17 06:55:39.491 2596-2596/mjt.myapplication D/DBINFO: Database contains Table newtable created by SQL CREATE TABLE newtable (Id INTEGER PRIMARY KEY, Name TEXT)
11-17 06:55:39.492 2596-2596/mjt.myapplication D/DBINFO: Table is newtable Column Count = 2 Row Count = 1
11-17 06:55:39.492 2596-2596/mjt.myapplication D/DBINFO: Columns are :- Id Name
11-17 06:55:39.492 2596-2596/mjt.myapplication D/DBINFO: logDatabaseTableInformation completed.
后一个Block显示有1个表,它被称为newtable,有2列1行。这些列名为Id和Name,表是使用SQL CREATE TABLE newtable (Id INTEGER PRIMARY KEY, Name TEXT)
创建的。
您的信息可能包含不同的信息。如果有任何以 sqllite_
开头的表名,您可以忽略它们。
假设输出如上,并且表名为 newtable ,那么您必须进行以下更改
String selectQuery="select Name from First where Id="+a+";";
到
MainActivity 中的 String selectQuery="select Name from newtable where Id="+a+";";
String selectQuery="select Name from First where Id="+a+";";
根据你在日志中的发现。
D/MAINDBCOPY: DB copied from assets.