无法将 db '/data/data/my.easymedi.controller/databases/EasyMediInfo.db' 的区域设置更改为 'en_US'
Posted
技术标签:
【中文标题】无法将 db \'/data/data/my.easymedi.controller/databases/EasyMediInfo.db\' 的区域设置更改为 \'en_US\'【英文标题】:Failed to change locale for db '/data/data/my.easymedi.controller/databases/EasyMediInfo.db' to 'en_US'无法将 db '/data/data/my.easymedi.controller/databases/EasyMediInfo.db' 的区域设置更改为 'en_US' 【发布时间】:2013-10-29 18:39:10 【问题描述】:在我的 android 应用程序中,资产文件夹中有一个预定义的数据库。
我创建了一个表 android_metadata
,其中有一列名为 locale
和一条记录 en_US
。
在我的应用程序中,用户应该输入他/她的详细信息并点击保存按钮。
点击保存按钮时出现以下错误;
10-21 09:37:06.010: E/SQLiteLog(6278): (11) [00bb9c9ce4] 第 50741 行的数据库损坏 10-21 09:37:06.010: E/SQLiteLog(6278): (11) [00bb9c9ce4] 第 50780 行的数据库损坏 10-21 09:37:06.010: E/SQLiteLog(6278): (11) 语句在 16 处中止:[SELECT locale FROM android_metadata UNION SELECT NULL ORDER BY locale DESC LIMIT 1] 10-21 09:37:06.160: E/SQLiteDatabase(6278): 无法打开数据库'/data/data/my.easymedi.controller/databases/EasyMediInfo.db'。 10-21 09:37:06.160: E/SQLiteDatabase(6278): android.database.sqlite.SQLiteException: 无法将 db '/data/data/my.easymedi.controller/databases /EasyMediInfo.db' 的区域设置更改为 ' en_US'。 10-21 09:37:06.160: E/SQLiteDatabase(6278): 在 android.database.sqlite.SQLiteConnection.setLocaleFromConfiguration(SQLiteConnection.java:386) 10-21 09:37:06.160: E/SQLiteDatabase(6278): 在 android.database.sqlite.SQLiteConnection.open(SQLiteConnection.java:218) 10-21 09:37:06.160: E/SQLiteDatabase(6278): 在 android.database.sqlite.SQLiteConnection.open(SQLiteConnection.java:193) 10-21 09:37:06.160: E/SQLiteDatabase(6278): 在 android.database.sqlite.SQLiteConnectionPool.openConnectionLocked(SQLiteConnectionPool.java:463) 10-21 09:37:06.160: E/SQLiteDatabase(6278): 在 android.database.sqlite.SQLiteConnectionPool.open(SQLiteConnectionPool.java:185) 10-21 09:37:06.160: E/SQLiteDatabase(6278): 在 android.database.sqlite.SQLiteConnectionPool.open(SQLiteConnectionPool.java:177) 10-21 09:37:06.160: E/SQLiteDatabase(6278): 在 android.database.sqlite.SQLiteDatabase.openInner(SQLiteDatabase.java:804) 10-21 09:37:06.160: E/SQLiteDatabase(6278): 在 android.database.sqlite.SQLiteDatabase.open(SQLiteDatabase.java:789) 10-21 09:37:06.160: E/SQLiteDatabase(6278): 在 android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:694) 10-21 09:37:06.160: E/SQLiteDatabase(6278): 在 android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:669) 10-21 09:37:06.160: E/SQLiteDatabase(6278): 在 my.easymedi.db.DBHelper.openDataBase(DBHelper.java:153) 10-21 09:37:06.160: E/SQLiteDatabase(6278): 在 my.easymedi.controller.AddNewPerson.onClick(AddNewPerson.java:202) 10-21 09:37:06.160: E/SQLiteDatabase(6278): 在 android.view.View.performClick(View.java:4202) 10-21 09:37:06.160: E/SQLiteDatabase(6278): 在 android.view.View$PerformClick.run(View.java:17340) 10-21 09:37:06.160: E/SQLiteDatabase(6278): 在 android.os.Handler.handleCallback(Handler.java:725) 10-21 09:37:06.160: E/SQLiteDatabase(6278): 在 android.os.Handler.dispatchMessage(Handler.java:92) 10-21 09:37:06.160: E/SQLiteDatabase(6278): 在 android.os.Looper.loop(Looper.java:137) 10-21 09:37:06.160: E/SQLiteDatabase(6278): 在 android.app.ActivityThread.main(ActivityThread.java:5039) 10-21 09:37:06.160: E/SQLiteDatabase(6278): 在 java.lang.reflect.Method.invokeNative(Native Method) 10-21 09:37:06.160: E/SQLiteDatabase(6278): 在 java.lang.reflect.Method.invoke(Method.java:511) 10-21 09:37:06.160: E/SQLiteDatabase(6278): 在 com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:793) 10-21 09:37:06.160: E/SQLiteDatabase(6278): 在 com.android.internal.os.ZygoteInit.main(ZygoteInit.java:560) 10-21 09:37:06.160:E/SQLiteDatabase(6278):在 dalvik.system.NativeStart.main(本机方法) 10-21 09:37:06.160:E/SQLiteDatabase(6278):原因:android.database.sqlite.SQLiteDatabaseCorruptException:数据库磁盘映像格式错误(代码 11) 10-21 09:37:06.160: E/SQLiteDatabase(6278): 在 android.database.sqlite.SQLiteConnection.nativeExecuteForString(Native Method) 10-21 09:37:06.160: E/SQLiteDatabase(6278): 在 android.database.sqlite.SQLiteConnection.executeForString(SQLiteConnection.java:634) 10-21 09:37:06.160: E/SQLiteDatabase(6278): 在 android.database.sqlite.SQLiteConnection.setLocaleFromConfiguration(SQLiteConnection.java:367) 10-21 09:37:06.160: E/SQLiteDatabase(6278): ... 22 更多
我的 DBHelper 课程正在关注;
package my.easymedi.db;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import my.easymedi.entity.Person;
import android.content.ContentValues;
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteException;
import android.database.sqlite.SQLiteOpenHelper;
import android.util.Log;
import android.widget.Toast;
public class DBHelper extends SQLiteOpenHelper
private static final String pkg = "my.easymedi.controller";
private static String DB_PATH = "";
private static String DB_NAME = "EasyMediInfo.db";
private static final int DB_VERSION = 1;
private final Context myContext;
private SQLiteDatabase myDatabase;
public DBHelper(Context context)
super(context, DB_NAME, null, DB_VERSION);
// this.myContext = context;
if (android.os.Build.VERSION.SDK_INT >= 4.2)
DB_PATH = context.getApplicationInfo().dataDir + "/databases/";
else
DB_PATH = "/data/data/" + context.getPackageName() + "/databases/";
this.myContext = context;
public void createDataBase()
boolean dbExist = checkDataBase();
System.out.println("===" + dbExist + "===");
if (dbExist)
// do nothing - database already exist
else
this.getReadableDatabase();
this.close();
try
copyDataBase();
Log.d("CREATE_DB", "createDatabase database created");
catch (IOException e)
Toast.makeText(myContext, e.getMessage(), Toast.LENGTH_SHORT)
.show();
Log.d("CREATE_DB", e.getMessage());
private void copyDataBase() throws IOException
System.out.println("***copy db***");
InputStream databaseInput = null;
/* Path to copy the database */
String outFileName = DB_PATH + DB_NAME;
/* open the empty database as an output stream */
OutputStream databaseOutput = new FileOutputStream(outFileName);
/* open the local database as the input stream */
databaseInput = myContext.getAssets().open(DB_NAME);
/* Transfer byte from byte from input file to output file */
byte[] buffer = new byte[1024];
int length = databaseInput.read(buffer);
while (length > 0)
databaseOutput.write(buffer, 0, length);
//databaseOutput.flush();
databaseOutput.flush();
databaseInput.close();
databaseOutput.close();
private boolean checkDataBase()
File dbFile = new File(DB_PATH + DB_NAME);
return dbFile.exists();
/*SQLiteDatabase checkDB = null;
try
String myPath = DB_PATH + DB_NAME;
checkDB = SQLiteDatabase.openDatabase(myPath, null,
SQLiteDatabase.NO_LOCALIZED_COLLATORS);
catch (SQLiteException e)
Toast.makeText(myContext, e.getMessage(), Toast.LENGTH_SHORT)
.show();
Log.d("Check_DB", e.getMessage());
if (checkDB != null)
String str = "checked";
System.out.println("====" + str + "====");
checkDB.close();
return checkDB != null ? true : false;*/
/* Open the database */
public boolean openDataBase()
String myPath = DB_PATH + DB_NAME;
Toast.makeText(myContext, myPath, Toast.LENGTH_SHORT).show();
myDatabase = SQLiteDatabase.openDatabase(myPath, null,
SQLiteDatabase.OPEN_READWRITE);
if (myDatabase != null)
System.out.println("====database opened====");
else
System.out.println("====error opening database====");
return myDatabase != null ? true : false;
public void closeDatabase()
if (myDatabase != null)
myDatabase.close();
@Override
public void onCreate(SQLiteDatabase db)
// TODO Auto-generated method stub
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion)
// TODO Auto-generated method stub
public boolean insertIntoDatabase(String table, ContentValues values)
try
myDatabase.insert(table, null, values);
Log.d("INSERT", "Information Saved");
return true;
catch (Exception e)
// TODO Auto-generated catch block
Log.d("INSERT", e.toString());
return false;
这是我保存按钮的代码段;
case R.id.btnSave: personName = etName.getText().toString();
date_of_birth = tvDOB.getText().toString();
age = tvAge.getText().toString();
int selected_rb_ID = genderGrp.getCheckedRadioButtonId();
RadioButton rb = (RadioButton) findViewById(selected_rb_ID);
gender = rb.getText().toString();
bloodGrp = spiBloodGrp.getSelectedItem().toString();
Person person = new Person();
person.setName(personName);
person.setDate_of_birth(date_of_birth);
person.setAge(age);
person.setGender(gender);
person.setBloodGrp(bloodGrp);
ContentValues values = new ContentValues();
values.put(COLUMN_PERSON_NAME, person.getName());
values.put(COLUMN_DOB, person.getDate_of_birth());
values.put(COLUMN_AGE, person.getAge());
values.put(COLUMN_GENDER, person.getGender());
values.put(COLUMN_BLOODGRP, person.getBloodGrp());
DBHelper dbHelper = new DBHelper(this);
dbHelper.createDataBase();
dbHelper.openDataBase();
if (dbHelper.insertIntoDatabase("EMPerson", values))
Toast.makeText(
getApplicationContext(),
"Data has been saved successfully",
Toast.LENGTH_SHORT
).show();
else
Toast.makeText(
getApplicationContext(),
"Oops ! Try again",
Toast.LENGTH_SHORT
).show();
dbHelper.closeDatabase();
break;
在我的主要活动中,我通过调用此代码段创建了数据库。
final DBHelper helper = new DBHelper(this);
helper.createDataBase();
这个错误是什么意思,我该如何解决?
【问题讨论】:
Android SQLiteException: Failed to change locale for db to 'en_US' 的可能重复项 【参考方案1】:您的 copyDataBase()
函数会从 assets 文件夹中复制一个 db(EasyMediInfo.db
)。而且似乎该数据库是使用与'en_US'
不同的语言环境创建的。
编辑
尝试改变:
myDatabase = SQLiteDatabase.openDatabase(myPath, null, SQLiteDatabase.OPEN_READWRITE);
收件人:
myDatabase = SQLiteDatabase.openDatabase(myPath, null, SQLiteDatabase.NO_LOCALIZED_COLLATORS | SQLiteDatabase.OPEN_READWRITE);
【讨论】:
如果我不使用 SQLiteDatabase.openDatabase 方法而是使用 dBHelper.getWritableDatabase() 怎么办? @AhesanaliMomin 你得到答案了吗? 我没有得到任何答案 所以我检查了完整的堆栈跟踪,发现这是`由 android.database.sqlite.SQLiteDatabaseLockedException 引起的` 因为我不确定使用 SQLiteDatabase.NO_LOCALIZED_COLLATORS 时会发生什么(考虑到排序行为)我不愿意更改代码。所以我只是将表“android_metadata”中“locale”列的值更改为异常中给出的值(例如帖子开头的 en_US)。这对我有用。【参考方案2】:我在 setLocale 到 zh_CN 时遇到了同样的错误。 我没有编写新代码直接使用 SQLiteDatabase,而是进行了修改 SQLiteOpenHelper:
/**
* A simplified version of SKD's SQLiteOpenHelper(only writable), original doc below
*
* A helper class to manage database creation and version management.
*
* <p>You create a subclass implementing @link #onCreate, @link #onUpgrade and
* optionally @link #onOpen, and this class takes care of opening the database
* if it exists, creating it if it does not, and upgrading it as necessary.
* Transactions are used to make sure the database is always in a sensible state.
*
* <p>This class makes it easy for @link android.content.ContentProvider
* implementations to defer opening and upgrading the database until first use,
* to avoid blocking application startup with long-running database upgrades.
*
* <p>For an example, see the NotePadProvider class in the NotePad sample application,
* in the <em>samples/</em> directory of the SDK.</p>
*
* <p class="note"><strong>Note:</strong> this class assumes
* monotonically increasing version numbers for upgrades.</p>
*/
public abstract class SQLiteOpenHelper
private static final String TAG = SQLiteOpenHelper.class.getSimpleName();
private final Context mContext;
private final String mName;
private final CursorFactory mFactory;
private final int mNewVersion;
private SQLiteDatabase mDatabase;
private boolean mIsInitializing;
private boolean mEnableWriteAheadLogging;
private final DatabaseErrorHandler mErrorHandler;
/**
* Create a helper object to create, open, and/or manage a database.
* This method always returns very quickly. The database is not actually
* created or opened until one of @link #getWritableDatabase or
* @link #getReadableDatabase is called.
*
* @param context to use to open or create the database
* @param name of the database file, or null for an in-memory database
* @param factory to use for creating cursor objects, or null for the default
* @param version number of the database (starting at 1); if the database is older,
* @link #onUpgrade will be used to upgrade the database; if the database is
* newer, @link #onDowngrade will be used to downgrade the database
*/
public SQLiteOpenHelper(Context context, String name, CursorFactory factory, int version)
this(context, name, factory, version, null);
/**
* Create a helper object to create, open, and/or manage a database.
* The database is not actually created or opened until one of
* @link #getWritableDatabase or @link #getReadableDatabase is called.
*
* <p>Accepts input param: a concrete instance of @link DatabaseErrorHandler to be
* used to handle corruption when sqlite reports database corruption.</p>
*
* @param context to use to open or create the database
* @param name of the database file, or null for an in-memory database
* @param factory to use for creating cursor objects, or null for the default
* @param version number of the database (starting at 1); if the database is older,
* @link #onUpgrade will be used to upgrade the database; if the database is
* newer, @link #onDowngrade will be used to downgrade the database
* @param errorHandler the @link DatabaseErrorHandler to be used when sqlite reports database
* corruption, or null to use the default error handler.
*/
public SQLiteOpenHelper(Context context, String name, CursorFactory factory, int version,
DatabaseErrorHandler errorHandler)
if (version < 1) throw new IllegalArgumentException("Version must be >= 1, was " + version);
mContext = context;
mName = name;
mFactory = factory;
mNewVersion = version;
mErrorHandler = errorHandler;
/**
* Return the name of the SQLite database being opened, as given to
* the constructor.
*/
public String getDatabaseName()
return mName;
/**
* Enables or disables the use of write-ahead logging for the database.
*
* Write-ahead logging cannot be used with read-only databases so the value of
* this flag is ignored if the database is opened read-only.
*
* @param enabled True if write-ahead logging should be enabled, false if it
* should be disabled.
*
* @see SQLiteDatabase#enableWriteAheadLogging()
*/
public void setWriteAheadLoggingEnabled(boolean enabled)
synchronized (this)
if (mEnableWriteAheadLogging != enabled)
if (mDatabase != null && mDatabase.isOpen() && !mDatabase.isReadOnly())
if (enabled)
mDatabase.enableWriteAheadLogging();
else
mDatabase.disableWriteAheadLogging();
mEnableWriteAheadLogging = enabled;
/**
Simplified getWritableDatabase from SDK source
*/
public SQLiteDatabase getWritableDatabase()
synchronized (this)
return getDatabaseLocked();
private SQLiteDatabase getDatabaseLocked()
// always get writable database
if (mDatabase != null)
if (!mDatabase.isOpen())
// Darn! The user closed the database by calling mDatabase.close().
mDatabase = null;
else if (!mDatabase.isReadOnly())
// The database is already open for business.
return mDatabase;
if (mIsInitializing)
throw new IllegalStateException("getDatabase called recursively");
SQLiteDatabase db = mDatabase;
try
mIsInitializing = true;
if (db == null && mName == null)
db = SQLiteDatabase.create(null);
else if (db == null)
try
final String path = mContext.getDatabasePath(mName).getPath();
db = SQLiteDatabase.openDatabase(path, mFactory,
(SQLiteDatabase.CREATE_IF_NECESSARY
| SQLiteDatabase.OPEN_READWRITE
| SQLiteDatabase.NO_LOCALIZED_COLLATORS),
mErrorHandler);
catch (SQLiteException ex)
throw ex;
onConfigure(db);
final int version = db.getVersion();
if (version != mNewVersion)
db.beginTransaction();
try
if (version == 0)
onCreate(db);
else
if (version > mNewVersion)
onDowngrade(db, version, mNewVersion);
else
onUpgrade(db, version, mNewVersion);
db.setVersion(mNewVersion);
db.setTransactionSuccessful();
finally
db.endTransaction();
onOpen(db);
mDatabase = db;
return db;
finally
mIsInitializing = false;
if (db != null && db != mDatabase)
db.close();
/**
* Close any open database object.
*/
public synchronized void close()
if (mIsInitializing) throw new IllegalStateException("Closed during initialization");
if (mDatabase != null && mDatabase.isOpen())
mDatabase.close();
mDatabase = null;
/**
* Called when the database connection is being configured, to enable features
* such as write-ahead logging or foreign key support.
* <p>
* This method is called before @link #onCreate, @link #onUpgrade,
* @link #onDowngrade, or @link #onOpen are called. It should not modify
* the database except to configure the database connection as required.
* </p><p>
* This method should only call methods that configure the parameters of the
* database connection, such as @link SQLiteDatabase#enableWriteAheadLogging
* @link SQLiteDatabase#setForeignKeyConstraintsEnabled,
* @link SQLiteDatabase#setLocale, @link SQLiteDatabase#setMaximumSize,
* or executing PRAGMA statements.
* </p>
*
* @param db The database.
*/
public void onConfigure(SQLiteDatabase db)
/**
* Called when the database is created for the first time. This is where the
* creation of tables and the initial population of the tables should happen.
*
* @param db The database.
*/
public abstract void onCreate(SQLiteDatabase db);
/**
* Called when the database needs to be upgraded. The implementation
* should use this method to drop tables, add tables, or do anything else it
* needs to upgrade to the new schema version.
*
* <p>
* The SQLite ALTER TABLE documentation can be found
* <a href="http://sqlite.org/lang_altertable.html">here</a>. If you add new columns
* you can use ALTER TABLE to insert them into a live table. If you rename or remove columns
* you can use ALTER TABLE to rename the old table, then create the new table and then
* populate the new table with the contents of the old table.
* </p><p>
* This method executes within a transaction. If an exception is thrown, all changes
* will automatically be rolled back.
* </p>
*
* @param db The database.
* @param oldVersion The old database version.
* @param newVersion The new database version.
*/
public abstract void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion);
/**
* Called when the database needs to be downgraded. This is strictly similar to
* @link #onUpgrade method, but is called whenever current version is newer
* than requested one.
* However, this method is not abstract, so it is not mandatory for a customer to
* implement it. If not overridden, default implementation will reject downgrade and
* throws SQLiteException
*
* <p>
* This method executes within a transaction. If an exception is thrown, all changes
* will automatically be rolled back.
* </p>
*
* @param db The database.
* @param oldVersion The old database version.
* @param newVersion The new database version.
*/
public void onDowngrade(SQLiteDatabase db, int oldVersion, int newVersion)
throw new SQLiteException("Can't downgrade database from version "
+ oldVersion + " to " + newVersion);
/**
* Called when the database has been opened. The implementation
* should check @link SQLiteDatabase#isReadOnly before updating the
* database.
* <p>
* This method is called after the database connection has been configured
* and after the database schema has been created, upgraded or downgraded as necessary.
* If the database connection must be configured in some way before the schema
* is created, upgraded, or downgraded, do it in @link #onConfigure instead.
* </p>
*
* @param db The database.
*/
public void onOpen(SQLiteDatabase db)
【讨论】:
以上是关于无法将 db '/data/data/my.easymedi.controller/databases/EasyMediInfo.db' 的区域设置更改为 'en_US'的主要内容,如果未能解决你的问题,请参考以下文章
django.db.utils.ProgrammingError:无法将类型 uuid 转换为整数
odoo 12 psycopg2.OperationalError:无法将主机名“db”转换为地址