Android学习笔记之(五):数据储存

  • Post author:
  • Post category:其他


一、Android系统中主要提供了三种方式用于简单的实现数据持久化功能即文件存储、SharePreference存储一级数据库存储。除此之外,还可以将数据保存在手机的SD卡中。

1、文件存储

1、写入数据:Context类中提供了一个openFileOutput()方法,此参数第一个参数是文件名。不能包含路径,因为所有文件都是存储到/data/data/<packagename>/file/目录下。第二个参数是文件的操作模式。即MODE_PRIVATE和MODE_APPEND。这两种模式表示所写入内容会覆盖原文件中的内容,而MODE_APPEND则是追加内容。

openFileOutput()方法返回的是一个FileOutputStream对象,用这个对象使用Java流的方式将数据写入文件中

	public void save(String inputText) 
	{
		FileOutputStream out = null;
		BufferedWriter writer = null;
		try {
			out = openFileOutput("data", Context.MODE_PRIVATE);
			writer = new BufferedWriter(new OutputStreamWriter(out));
			writer.write(inputText);
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			try {
				if (writer != null) {
					writer.close();
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}

这里通过openFileOutput()的方法得到一个FileOutputStream对象,再借助它构建出一个OutputStreamWriter对象,接着再用

OutputStreamWriter构建出一个BufferedWriter对象,这样就可以通过BufferedWriter来将文本内容写到文件中




2、读取数据:与写文件相似,Context中有openFileInput(),用于从文件中读取数据。这个方法的参数就是需要读取的文件名,读取路径也是有系统自动从/data/data/<package name>/files/目录下去加载这个文件,并返回一个FileInputStream。
	public String load()
	{
		FileInputStream in = null;
		BufferedReader reader = null;
		StringBuilder content = new StringBuilder();
		try {
			in = openFileInput("data");
			reader = new BufferedReader(new InputStreamReader(in));
			String line = "";
			while ((line = reader.readLine()) != null) {
				content.append(line);
			}
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			if (reader != null) {
				try {
					reader.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
		return content.toString();
	}


这里的原理基本与写数据的原理相同


2、SharedPreferences存储

1、不同于文件的存储方式,SharePreferences是使用键值对的方式来存储数据。也就是说当保存一条数据的时候,需要这条数据提供一个对应的键,这样在读取数据的时候就可以通过这个键把相对应的值取出。
2、Context类中提供了getSharedPreferences方法,文件收拾存放在/data/data/<package name>/shared_prefs/目录下。 此方法接受两个参数,第一个是文件名,第二个是MODE_PRIVATE和MODE_MULTI_PROCESS。MODE_PRIVATE表示只有当前的应用程序才可以对这个SharedPreferences文件进行读写。MODE_MULTI_PROCESS则一般是用于会有多个进程中对同一个SharedPreferences文件进行读写的情况。
3、Context中还提供了另一个方法gePreferences()。他默认一个操作模式,所以他的参数只接收文件名。
4、PreferenceManager类中的getDufaultSharedPreferences()方法是一个静态方法,他接受一个Context参数,并自动使用当前应用程序的报名作为前缀来命名SharePreferences文件。
(1) 调用SharedPreferences对象的edit()方法来获取一个SharedPreferences.Editor对象。
(2) 向 SharedPreferences.Editor对象中添加数据,比如添加一个bool数据就是用puBoolean方法,添加一个字符串就使用putString()方法,一次类推。
(3)调用commit()方法将添加的数据提交,从而完成数据操作。
SharedPreferences.Editor editor = getSharedPreferences("data", MODE_PRIVATE).edit();
editor.putString("name", "Tom");
editor.putInt("age", 28);
editor.putBoolean("married", false);
editor.commit();


这里是通过getSharePreferences()方法指定SharePreferences的文件名为data,并得到了SharedPreferences.Editor对象。接着向这个对象中添加了三条不同类型的数据,最后调用commit()方法进项提交。  可从文件中找到data.xml文件





5、从SharedPreferences中读取文件。SharedPreferences对象中提供了一系列get方法来进行数据读取

SharedPreferences pref = getSharedPreferences("data", MODE_PRIVATE);
String name = pref.getString("name", "");
int age = pref.getInt("age", 0);
boolean married = pref.getBoolean("married", false);


这里调用了它的getString()、getInt()和getBoolean()方法去获取之前所存储的数据


3、SQLite数据库存储

1、android提供了一个SQLitOpenHelper帮助类,它是一个抽象类,它的两个抽象方法onCreate()和onUpgrade()。他还有两个实例方法getReadableDatabase()和getWritebleDatabase()。这两个方法一个是读操作,一个是写操作。
2、SQListOpenHelper中有两个构造函数可供重写,一般使用参数少的构造方法即可。第一个:Context,第二个:数据库名,第三个:参数允许我们在查询数据的时候返回一个自定义的Cursor,一般传入null。第四个:当前数据库的版本号。数据库文件一会存放在/data/data/<packge name>/databases/目录下。
public class MyDatabaseHelper extends SQLiteOpenHelper {

	public static final String CREATE_BOOK = "create table Book ("
			+ "id integer primary key autoincrement, "
			+ "author text, "
			+ "price real, "
			+ "pages integer, "
			+ "name text)";
	
	private Context mContext;
	
	public MyDatabaseHelper(Context context, String name,
			CursorFactory factory, int version) {
		super(context, name, factory, version);
		// TODO Auto-generated constructor stub
		mContext = context;
	}

	@Override
	public void onCreate(SQLiteDatabase db) {
		// TODO Auto-generated method stub
		db.execSQL(CREATE_BOOK);
		Toast.makeText(mContext, "Create succeeded", Toast.LENGTH_SHORT).show();
	}

	@Override
	public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
		// TODO Auto-generated method stub
	}

}


这里把建表的语句定义成了字符串常量,然后在onCreate()方法中调用了SQListDatabase的execSQL()方法去执行这条建表语句。

dbHelper = new MyDatabaseHelper(this, "BookStore.db", null, 1);
dbHelper.getWritableDatabase();
这里构建了一个MyDatabaseHelper对象,并通过构造函数的参数将数据名指定为BookStore.db,版本号为1,然后调用getWritebleDatabase()方法时就会检测当前程序中并没有BookStore.db这个数据库,于是就会穿件数据库并调用MyDatabaseHelper中的onCreate()方法,这样Book表也就得到了创建。

3、升级数据库。在MyDatabaseHelper中的onUpgrade()方法是用于对数据库进行升级的,如果要在数据库中添加一张Catagory表,那么修改MyDatabaseHelper
public class MyDatabaseHelper extends SQLiteOpenHelper {

	public static final String CREATE_BOOK = "create table Book ("
			+ "id integer primary key autoincrement, "
			+ "author text, "
			+ "price real, "
			+ "pages integer, "
			+ "name text)";
	
	public static final String CREATE_CATEGORY = "create table Category ("
			+ "id integer primary key autoincrement, "
			+ "category_name text, "
			+ "category_code real)";
	
	private Context mContext;
	
	public MyDatabaseHelper(Context context, String name,
			CursorFactory factory, int version) {
		super(context, name, factory, version);
		// TODO Auto-generated constructor stub
		mContext = context;
	}

	@Override
	public void onCreate(SQLiteDatabase db) {
		// TODO Auto-generated method stub
		db.execSQL(CREATE_BOOK);
		db.execSQL(CREATE_CATEGORY);
		Toast.makeText(mContext, "Create succeeded", Toast.LENGTH_SHORT).show();
	}

	@Override
	public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
		// TODO Auto-generated method stub
	}

}


如果用以上方法去创建数据库的,Catagory将无法穿件,因为此时BookStore.db数据库已经存在,之后在调用MydatabaseHelper中的onCreate()方法都不再次执行,因此新添加的表也无法得到创建。这里只需要修改onUpgrade()函数

public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
	// TODO Auto-generated method stub
	db.execSQL("drop table if exists Book");
	db.execSQL("drop table if exists Category");
	onCreate(db);
}
这里执行了两条DROP语句,如果发现数据库中已经存在Book表或者Category表了,就将这两张表删掉,然后调用onCreate()方法去重新创建。只要在SQLiteOpenHelper的构造方法里的版本号比之前传入的大,就会执行onUpgrade()方法。

4、添加数据。数据谷的操作有四种CRUD。C:添加、R:查询、U:更新、D:删除。每一种操作又各自对应了一种SQL命令。之前调用的getReadableDatabase()或getWritableDatabase()都会返回一个SQListDatabase对象,借助这个对象就可以进行CRUD操作。
(1)SQListDatabase提供了一个insert()方法,它接收三个参数。1:表名、2:在未指定添加数据的情况下可为空的列自动复制NULL、3:ContentValues对象,他提供了一系列的put()方法重载。
SQLiteDatabase db = dbHelper.getWritableDatabase();
ContentValues values = new ContentValues();
// 开始组装第一条数据
values.put("name", "The Da Vinci Code");
values.put("author", "Dan Brown");
values.put("pages", 454);
values.put("price", 16.96);
db.insert("Book", null, values);
values.clear();

values.put("name", "The Da Vinci Code");
values.put("author", "Dan Brown");
values.put("pages", 454);
values.put("price", 16.96);
db.insert("Book", null, values);
values.clear();
这里先获取了SQLiteDatabase对象,然后使用ContentValues来对要添加的数据进行组装。这里id并没有给他赋值,丹他会自动增长

(2)

SQListDatabase提供了一个update()方法,它接收四个参数。1:表名、2:ContentValues对象、3,4:用于约束更新某一行或者某一行中的某个数据,不指定的话默认就是更新所有行。
dbHelper = new MyDatabaseHelper(this, "BookStore.db", null, 2);
SQLiteDatabase db = dbHelper.getWritableDatabase();
ContentValues values = new ContentValues();
values.put("price", 10.99);
db.update("Book", values , "name = ?", new String[] {"The Da Vinci Code"});
这里构建了一个ContentValues对象,并只给他指定了一组数据,把price更新成10.99。这里的第三、第四个参数来指定具体更新那几行。表示去更新name等于?的行,而?是一个占位符,可以通过第四个参数提供一个字符串数组为第三个参数中的每个占位符指定对应内容。所以,这里是将名字为The Da Vinci Code的价格改为10.99。
(3)

SQListDatabase提供了一个delete()方法,他接收三个参数。1:表名、2,3:用于约束删除某一行或者某几行的数据,不指定的话,默认删除所有行。
dbHelper = new MyDatabaseHelper(this, "BookStore.db", null, 2);
SQLiteDatabase db = dbHelper.getWritableDatabase();
db.delete("Book", "pages > ?", new String[] {"500"});

这里指明删除Book表中的数据,并且通过第二,第三个参数来指定仅删除那些页数超过500页的书籍。

(4)


SQListDatabase提供了一个query()方法,这个方法的参数非常复杂,最短的也需要七个参数。1:表名、2:指定去查询那几列,如果不指定则默认所有列、3,4:约束查询某一行或者某几行的数据,不指定则默认所有行、5:指定需要去group by的列,不指定则表示不对查询结果进行group bu操作、6:对group bu之后的数据进行进一步的过滤,不指定则表示不进行过滤、7:参数用于指定查询结果排序,不指定则…..
SQLiteDatabase db = dbHelper.getWritableDatabase();
Cursor cursor.close() = db.query("Book", null, null, null, null, null, null);

if (cursor.moveToFirst()) {
	do {
		// 遍历Cursor对象,去除数据打印
		String name = cursor.getString(cursor.getColumnIndex("name"));
		String author = cursor.getString(cursor.getColumnIndex("author"));
		int pages = cursor.getInt(cursor.getColumnIndex("pages"));
		double price = cursor.getDouble(cursor.getColumnIndex("price"));
	} while(cursor.moveToNext());
}
cursor.close()


这里的query()只使用了第一个参数指明去查询Book表,表示查询表的所有数据。Cursor对象调用moveToFirst()方法将数据的指针移到第一行的位置,然后遍历查询每一行的数据。在通过getColumnIndex()方法获取到某一列在表中对应位置的索引,然后将这个索引传入对应的取值方法中。最后调用close()方法来关闭Cursor。



版权声明:本文为yu384453511原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。