创建数据库的时候就将数据库保存到SDcard中
2011-01-03 16:53 雪夜&流星 阅读(2102) 评论(0) 编辑 收藏 举报我们知道数据库创建的时候默认保存到系统data/data/项目名 下面了,有没有一种方法保存到自己指定的SDCard上的文件夹里面呢?答案是可以的。我们只需要找到SQLiteOpenHelper这个类,了解一下就不难发现其保存的路径是固定了的,那么我们只需要改动一下getWritableDatabase(),即写入的时候的路径:
public synchronized SQLiteDatabase getWritableDatabase() {
if (mDatabase != null && mDatabase.isOpen() && !mDatabase.isReadOnly()) {
return mDatabase; // The database is already open for business
}
if (mIsInitializing) {
throw new IllegalStateException("getWritableDatabase called recursively");
}
// If we have a read-only database open, someone could be using it
// (though they shouldn't), which would cause a lock to be held on
// the file, and our attempts to open the database read-write would
// fail waiting for the file lock. To prevent that, we acquire the
// lock on the read-only database, which shuts out other users.
boolean success = false;
SQLiteDatabase db = null;
if (mDatabase != null) mDatabase.lock();
try {
mIsInitializing = true;
if (mName == null) {
db = SQLiteDatabase.create(null);
} else {
db = mContext.openOrCreateDatabase(mName, 0, mFactory);
}
int version = db.getVersion();
if (version != mNewVersion) {
db.beginTransaction();
try {
if (version == 0) {
onCreate(db);
} else {
onUpgrade(db, version, mNewVersion);
}
db.setVersion(mNewVersion);
db.setTransactionSuccessful();
} finally {
db.endTransaction();
}
}
onOpen(db);
success = true;
return db;
} finally {
mIsInitializing = false;
if (success) {
if (mDatabase != null) {
try { mDatabase.close(); } catch (Exception e) { }
mDatabase.unlock();
}
mDatabase = db;
} else {
if (mDatabase != null) mDatabase.unlock();
if (db != null) db.close();
}
}
}
注意标志的红色的部分,这是创建数据库的地方,我们再看看openOrCreateDatabase()
这个方法,openOrCreateDatabase()这个方法存在于package android.content;下面的public abstract class Context{}类里面,
public abstract SQLiteDatabase openOrCreateDatabase(String name,int mode, CursorFactory factory);
我们发现在package android.database.sqlite;包下的public class SQLiteDatabase extends SQLiteClosable {}里面也有一个
public static SQLiteDatabase openOrCreateDatabase(String path, CursorFactory factory) {
return openDatabase(path, factory, CREATE_IF_NECESSARY);
}
相同的方法,只是参数不同,这个可以传一个路径进去,我们就调用这个方法。
然后我们还要有一个我们指定文件夹的路径的方法:
public File getDatabasePath(String name) {
String EXTERN_PATH = null;
//判断是否有SDcard
if(Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)==true)
{
//判断是否存在指定的文件夹,如果没有就创建它
EXTERN_PATH = android.os.Environment.getExternalStorageDirectory().getAbsolutePath()
+ "/database/";
File f=new File(EXTERN_PATH);
if(!f.exists())
{
f.mkdirs();
}
}
return new File(EXTERN_PATH+ name);
}
及对SDcard进行写和读的权限:
<!-- 在SDCard中创建于删除文件权限 -->
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />
<!-- 往SDCard写入数据权限 -->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
最后当我们创建数据库的时候直接继承我们自己定义的SDSQLiteOpenHelper(),不用系统自带SQLiteOpenHelper()即可。
参考我在eoeAndroid中文章:http://www.eoeandroid.com/thread-53985-1-1.html
自已定义的SDSQLiteOpenHelper():
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 | public abstract class SDSQLiteOpenHelper { private static final String TAG = SDSQLiteOpenHelper. class .getSimpleName(); @SuppressWarnings ( "unused" ) private final Context mContext; private final String mName; private final CursorFactory mFactory; private final int mNewVersion; private SQLiteDatabase mDatabase = null ; private boolean mIsInitializing = false ; /** * 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. * * @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 */ public SDSQLiteOpenHelper(Context context, String name, CursorFactory factory, int version) { if (version < 1 ) throw new IllegalArgumentException( "Version must be >= 1, was " + version); mContext = context; mName = name; mFactory = factory; mNewVersion = version; } /** * Create and/or open a database that will be used for reading and writing. * Once opened successfully, the database is cached, so you can call this * method every time you need to write to the database. Make sure to call * {@link #close} when you no longer need it. * * <p> * Errors such as bad permissions or a full disk may cause this operation to * fail, but future attempts may succeed if the problem is fixed. * </p> * * @throws SQLiteException * if the database cannot be opened for writing * @return a read/write database object valid until {@link #close} is called */ public synchronized SQLiteDatabase getWritableDatabase() { if (mDatabase != null && mDatabase.isOpen() && !mDatabase.isReadOnly()) { return mDatabase; // The database is already open for business } if (mIsInitializing) { throw new IllegalStateException( "getWritableDatabase called recursively" ); } // If we have a read-only database open, someone could be using it // (though they shouldn't), which would cause a lock to be held on // the file, and our attempts to open the database read-write would // fail waiting for the file lock. To prevent that, we acquire the // lock on the read-only database, which shuts out other users. boolean success = false ; SQLiteDatabase db = null ; try { mIsInitializing = true ; if (mName == null ) { db = SQLiteDatabase.create( null ); } else { String path = getDatabasePath(mName).getPath(); db = SQLiteDatabase.openOrCreateDatabase(path, mFactory); } int version = db.getVersion(); if (version != mNewVersion) { db.beginTransaction(); try { if (version == 0 ) { onCreate(db); } else { onUpgrade(db, version, mNewVersion); } db.setVersion(mNewVersion); db.setTransactionSuccessful(); } finally { db.endTransaction(); } } onOpen(db); success = true ; return db; } finally { mIsInitializing = false ; if (success) { if (mDatabase != null ) { try { mDatabase.close(); } catch (Exception e) { } } mDatabase = db; } else { if (db != null ) db.close(); } } } /** * Create and/or open a database. This will be the same object returned by * {@link #getWritableDatabase} unless some problem, such as a full disk, * requires the database to be opened read-only. In that case, a read-only * database object will be returned. If the problem is fixed, a future call * to {@link #getWritableDatabase} may succeed, in which case the read-only * database object will be closed and the read/write object will be returned * in the future. * * @throws SQLiteException * if the database cannot be opened * @return a database object valid until {@link #getWritableDatabase} or * {@link #close} is called. */ public synchronized SQLiteDatabase getReadableDatabase() { if (mDatabase != null && mDatabase.isOpen()) { return mDatabase; // The database is already open for business } if (mIsInitializing) { throw new IllegalStateException( "getReadableDatabase called recursively" ); } try { return getWritableDatabase(); } catch (SQLiteException e) { if (mName == null ) throw e; // Can't open a temp database read-only! Log.e(TAG, "Couldn't open " + mName + " for writing (will try read-only):" , e); } SQLiteDatabase db = null ; try { mIsInitializing = true ; String path = getDatabasePath(mName).getPath(); db = SQLiteDatabase.openDatabase(path, mFactory, SQLiteDatabase.OPEN_READWRITE); if (db.getVersion() != mNewVersion) { throw new SQLiteException( "Can't upgrade read-only database from version " + db.getVersion() + " to " + mNewVersion + ": " + path); } onOpen(db); Log.w(TAG, "Opened " + mName + " in read-only mode" ); mDatabase = db; return mDatabase; } 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 ; } } public File getDatabasePath(String name) { String EXTERN_PATH = null ; if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)== true ) { EXTERN_PATH = android.os.Environment.getExternalStorageDirectory().getAbsolutePath() + "/db/" ; File f= new File(EXTERN_PATH); if (!f.exists()) { f.mkdirs(); } } return new File(EXTERN_PATH+ name); } /** * 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. * * @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 has been opened. Override method should check * {@link SQLiteDatabase#isReadOnly} before updating the database. * * @param db * The database. */ public void onOpen(SQLiteDatabase db) { } } |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本