Android学习笔记 --- 数据存储与访问 (File,sdcard,sharedpreferences,sqlite)
一、 使用文件进行数据存储
1.context.openFileOutput()方法 写入文件内容
在上下文context中 openFileOutput方法可以用于把数据输出到文件中
示例代码:
public static void fileStorage(Context context){
try {
FileOutputStream fos = context.openFileOutput("filedata.txt", context.MODE_PRIVATE);
fos.write("文件存储".getBytes());
fos.flush();
fos.close();
} catch (Exception e) {
e.printStackTrace();
}
}
openFileOutput()方法 的第一个参数用于指定文件名称,不能包含路径分隔符“/”,如果文件不存在,会自动创建,创建的文件保存在/data/data/包名/files目录下 如:/data/data/cn.itcast/files/itcast.txt
openFIleOutput()方法的第二个参数用于指定操作模式,有四种模式,分别为:
Context.MODE_PRIVATE = 0
Context.MODE_APPEND = 32768
Context.MODE_WORLD_READABLE = 1
Context.MODE_WORLD_WRITEABLE = 2
Context.MODE-PRIVATE:为默认操作模式,代表该文件是私有数据,只能被应用本身访问,在该模式下,写入的内容会覆盖原文件的内容,如果想把新写入的内容追加到源文件中,可以使用Context.MODE_APPEND
Context.MODE-APPEND: 模式会检查文件是否存在,存在就往文件中追加内容,否则就创建文件
Context.MODE_WORLD_READABLE 和 Context.MODE_WORLD_WRITEABLE用来控制其他应用是否有权限读写该文件
Context.MODE_WORLD_READABLE: 表示当前文件可以被其他应用程序读取
Context.MODE_WORLD_WRITERABLE: 表示当前文件可以被其他应用写入
如果希望文件被其他应用程序读和写,可以传入:
openFileOutput("filestorage.text",Context.MODE_WORLD_READABLE + Context.MODE_WORLD_WRITEABLE);
Android有一套自己的安全模型,当应用程序(.apk)在安装时系统就会分配给他一个userid,当该应用要去访问其他资源时,如访文件的时候,就需要userid匹配。
默认情况下,任何应用创建的文件,sharepreferences,数据库都应该是私有的(位于/data/data/包名/files),其他程序无法访问。除非在创建时指定了Context.MODE_WORLD_READABLE或Context.MODE_WORLD_WRITEABLE,只有这样其他程序才能正确访问。
2.读取文件内容
如果打开存放在/data/data/包名/files目录应用私有的文件,可以使用Activity提供的openFileInput()方法
FileInputStream fis = context.openFileInput("fileStorage2.txt");
BufferedReader br = new BufferedReader(new InputStreamReader(fis));
String data = br.readLine();
System.out.println("data:" + data);
或者直接使用该文件的绝对路径:
File file = new File("/data/data/包名/files/文件名"):
FileInputStream fis = new FileInputStream(file);
BufferedReader br = new BufferedReader(new InputStreamReader(fis));
String data = br.readLine();
System.out.println("data:" + data);
对于私有文件只能被创建该文件的应用访问,如果希望文件能被其他应用读和写,可以在创建文件时,指定Context.MODE_WORLD_READABLE 和 Context.MODE_WORLD_WRITERABLEz权限
Activity还提供了getCacheDir() 和 getFileDir()方法
getCacheDir()方法 用于获取 /data/data/包名/cache目录 ----- 获取缓存信息
getFileDir()方法 用于获取/data/data/包名/files目录
==================================================================================
二、文件存储在SDCard
1.存储到SDCard
使用Activityd openFileOutput()方法保存文件,文件是存放在手机空间上,一般手机的存储孔家不是很大,存放写小文件还好,但一般不能存放大文件,如视频等
在模拟器中使用SDCard,你需要先创建一个具有SDCard的模拟器
在程序中访问SDCard,你需要申请访问SDCard的权限。
//
挂在和卸载SDCard的权限
android.premission.MOUNT_UNMOUNT_FILESTSTEMS
// 写入外部存储设备的权限
android.permission. WRITE_EXTERNAL_STORAGE
要往SDCard存放文件,程序必须先检验手机是否有SDCard的存在,并且可以进行读写。
注意:访问SDCard必须在AndroidManifest.xml中加入访问SDCard的权限
if(Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)){
// 判断是否有sd卡 Environment.getExternalStorageState()方法用于获取SDCard的状态,
// 如果手机装有SDCard,并且可以进行读写,那么方法返回的状态等于Environment.MEDIA_MOUNTED。
File sdCardDir = Environment.getExternalStorageDirectory(); // 获得sdCard卡的路径
File file = new File(sdCardDir,"sdCardStorage.txt");
try {
if(!file.exists()){
// 如果文件不存在 则创建该文件
file.createNewFile();
}
FileOutputStream fos = new FileOutputStream(file);
fos.write("SD卡存储".getBytes());
fos.flush();
fos.close();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
2.从SDCard中取出数据
添加从SDCard中取出数据的权限 : android.permission.READ_EXTERNAL_STORAGE
if(Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)){
// 判断内存卡是否存在
File sdCardDir = Environment.getExternalStorageDirectory();
File file = new File(sdCardDir,"sdCardStorage.txt");
try {
FileInputStream fis = new FileInputStream(file);
BufferedReader br = new BufferedReader(new InputStreamReader(fis));
String data = br.readLine();
System.out.println("data:" + data);
fis.close();
br.close();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
==================================================================================
三、使用SharedPreferences进行数据存储
1.存储数据
SharedPreferences类,是一个轻量级存储类,特别适合用于保存软件配置参数。使用SharedPreferences保存数据,其实质上是用xml文件存放数据,文件存放在/data/data/包名/shared_prefs目录下
常用来保存:qq登录信息,简单的配置信息,状态,标识等。
SharedPreferences sp = context.getSharedPreferences("sharedPre", context.MODE_PRIVATE);
Editor editor = sp.edit(); // 获得编辑器
editor.putString("spStorage", "SharedPreferences方式保存数据");
editor.commit(); // 提交
生成的xml文件如下:
<?xml version='1.0' encoding='utf-8' standalone='yes' ?>
<map>
<string name="spStorage">SharedPreferences方式保存数据</string>
</map>
因为SharedPreferences背后是使用xml文件保存数据,getSharedPreferences(name,mode)方法的第一个参数用于指定该文件的名称,名称后面不用带后缀.xml,后缀由Android自动加上。方法的第二个参数指定文件的操作模式,共有四种操作模式,即是前面所写的那四种模式。
如果希望SharedPreferences背后使用的xml文件能被其他应用程序读和写,可以指定Context.MODE_WORLD_READABLE和Context.MODE_WORLD_WRITEABLE权限。
另外Activity还提供了另一个getPreferences(mode)方法操作SharedPreferences,这个方法默认使用当前类不带包名的类名作为文件的名称。
2.访问SharedPreferences 中的数据
SharedPreferences sp = context.getSharedPreferences("sharedPre", context.MODE_PRIVATE);
String data = sp.getString("spStorage", null);
System.out.println("data:" + data);
sp.getString(key, defValue);方法 第一个参数是键key,根据key查找对应的值value,如果没找到,则返回第二个参数defValue(默认值)
四、Sqlite数据库存储
Sqlite 是一款轻型的数据库,是遵守ACID(原子性、一致性、隔离性、持久性)的关联式数据库管理系统,多用于嵌入式开发中。
唯一例外的是:integer primary key 此字段只能存储64为整数
在Android系统中,提供了SQLiteOpenHelper抽象类,该类用于对数据库版本进行管理,该类中常用的方法:
onCreate 数据库创建时调用此方法(第一次连接获取数据库对象时执行)
onUpgrade 数据库更新时调用此方法(版本号改变时执行)
onOpen 数据库每次打开时执行(每次打开数据库时调用哦,在onCreate、onUpgrade方法之后
1.使用SQLiteDatabase操作SQLite数据库
Android提供了一个名为SQLiteDatabase的类,该类封装了一些操作数据库的API,使用该类可以完成对数据的添加(Create)、查询(Retrieve)、更新(Update)和删除(Delete),这些操作简称为( CRUD)
execSQL()方法可以执行insert、delete、update和CREATE TABLE之类有更改行为的SQL语句; rawQuery()方法用于执行select语句(查询query)。
SQLiteOpenHelper抽象类:
public class MySqliteOpenHelper extends SQLiteOpenHelper {
public MySqliteOpenHelper(Context context) {
super(context, "database.db", null, 1);
}
/**
* 数据库创建时调用
*/
@Override
public void onCreate(SQLiteDatabase db) {
String sql = "create table database (_id integer primary key autoincrement,name varchar(20),age varchar(20))";
db.execSQL(sql);
}
/**
* 数据库更新时调用
*/
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
// TODO Auto-generated method stub
}
}
数据库的增删改查操作:
/**
* 数据库帮助类
*/
private MySqliteOpenHelper helper;
public DatabaseUtils(Context context){
helper = new MySqliteOpenHelper(context);
}
/**
* 将数据插入数据库
*/
public void insert(){
SQLiteDatabase db = helper.getWritableDatabase();
String sql = "insert into database values(null,'zhangsan','20')";
db.execSQL(sql);
db.close();
}
/**
* 更新数据库中的数据
*/
public void update(){
SQLiteDatabase db = helper.getWritableDatabase();
ContentValues values = new ContentValues();
values.put("name", "lisi");
db.update("database", values, "name = ?", new String []{"zhangsan"});
db.close();
}
/**
* 查询数据库 中的数据
*/
public void query(){
SQLiteDatabase db = helper.getReadableDatabase();
String sql = "select name,age from database";
Cursor cursor = db.rawQuery(sql, null);
while(cursor != null && cursor.moveToNext()){ // cursor 不为null 防止出现空指针异常 moveToNext ()移动到下一行
String name = cursor.getString(0); // 获得第一列的值,第一列的索引从0开始
int age = cursor.getInt(1); // 获得第二类的值
System.out.println("name : " + name + "," + "age :" + age);
}
cursor.close();
db.close();
}
/**
* 删除数据库中的数据
*/
public void delete(){
SQLiteDatabase db = helper.getWritableDatabase();
db.delete("database", null, null);
db.close();
}
Cursor是结果集游标,用于对结果集进行随机访问,与jdbc中的ResultSet作用很相似。使用moveToNext()方法可以将游标从当前行移动到下一行,如果已经移到了最后吧一行,返回结果为false,否则为true。另外Cursor还用常用的moveToPrevious()方法(用于将游标从当前行移动到上一行,如果已经移动到了结果集的第一行,返回值为false,否则为true)、moveToFirst()方法(用于将游标移动到结果集的第一行,如果结果集为空,返回值为false,否则为true)和moveToLast()方法(用于将游标移动到结果集的最后一行,如果结果集为空,返回值为false,否则为true);
使用事务操作Sqlite数据库
SQLiteDatabase db = null;
try {
db = helper.getWritableDatabase();
db.beginTransaction(); // 开启事务
String sql = "insert into database values(null,'zhangsan','20')";
db.execSQL(sql);
db.execSQL("update database set name=? where age=?", new Object[]{"wangwu", 20});
db.setTransactionSuccessful(); // 调用此方法会在执行到endTransaction()方法时提交当前事务,如果不调用此方法会回滚事务
}finally{
if(db != null){
db.endTransaction(); // 事务的结束的标志,决定是提交事务还是回滚事务
}
}
db.close();
使用SQLiteDatabase的beginTransaction()方法可以开启一个事务,程序执行到endTransaction()方法时会检查事务的标志是否成功,如果程序执行到endTransaction()方法之前调用了setTransactionSuccessful()方法设置事务的标志为成功,则提交事务,如果没有调用setTransactionSuccessful()方法则回滚事务