Android之数据存储

本文详细介绍了Android平台上的数据存储方式,包括SharedPreferences用于存储配置信息,内部文件系统保存较大数据或图片,以及SQLite数据库用于结构化数据的存储。文中还涉及到SD卡的读写操作和SQLite数据库的使用,包括数据类型、事务管理和查询方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一,sp存储

SharedPreferences是Android平台上一个轻量级的存储类,主要是保存一些常用的配置比如窗口状态,一般在Activity中 重载窗口状态onSaveInstanceState保存一般使用SharedPreferences完成,它提供了Android平台常规的Long长 整形、Int整形、String字符串型的保存。

它的本质是基于XML文件存储key-value键值对数据,通常用来存储一些简单的配置信息。

其存储位置在/data/data/<包名>/shared_prefs目录下。

SharedPreferences对象本身只能获取数据而不支持存储和修改,存储修改是通过Editor对象实现。

SharedPreferences: 对应sp文件的接口
context. getSharedPreferences (String name, int mode): 得到SP对象
name: 文件名(不带.xml)
mode: 生成的文件模式(是否是私有的,即其它应用是否可以访问)
Editor sp.edit() : 得到Editor对象
Xxx sp.getXxx(name,defaultValue): 根据name得到对应的数据
Editor : 能更新sp文件的接口
 Editor put(name, value) : 保存一个键值对, 没有真正保存到文件中
Editor remove(name)
commit(): 提交, 数据真正保存到文件中了

1.sp存储的保存数据

public void save(View v) {
		//2.得到Editor对象
		Editor edit=sp.edit();
		//3.得到输入的key/value
		String key = et_sp_key.getText().toString();
		String value = et_sp_value.getText().toString();
		//4.使用Editor保存key-value
		edit.putString(key, value).commit();
		//5.提示
		Toast.makeText(this, "保存完成", 0).show();
	}
2.sp存储的读取数据

	public void read(View v) {
		//1.得到输入的key
		String key = et_sp_key.getText().toString();
		//2.根据key读取对应的value
		String value = sp.getString(key, null);
		//3.显示
		if(value==null){
			Toast.makeText(this, "没有找到对应的value", 0).show();
		}else{
			et_sp_value.setText(value);
		}
	}
二,手机内部文件存储

应用运行需要的一些较大的数据或图片可以用文件保存的手机内部
文件类型: 任意
数据保存的路径: /data/data/projectPackage/files/
可以设置数据只能是当前应用读取, 而别的应用不可以
应用卸载时会删除此数据

读取文件:FileInputStream fis = openFileInput("logo.png");
保存文件:FileOutputStream fos = openFileOutput("logo.png", MODE_PRIVATE)
得到files文件夹对象:File filesDir = getFilesDir();  
操作asserts下的文件
得到AssetManager : context.getAssets();
读取文件: InputStream open(filename);
加载图片文件:Bitmap BitmapFactory.decodeFile(String pathName)   // .bmp/.png/.jpg
1.保存数据:

	public void save(View v) throws IOException {
		//1.得到InputStream-->读取assets下的logo.png
			//得到AssetManager
		AssetManager manager = getAssets();
		//读取文件
		InputStream is = manager.open("logo.png");
		//2.得到OutputStream-->/data/data/packageName/files/logo.png
		FileOutputStream fos = openFileOutput("logo.png", Context.MODE_PRIVATE);
		//3.边读边写
		byte[] buffer=new byte[1024];
		int len = -1;
		while((len = is.read(buffer))!=-1){
			fos.write(buffer,0,len);
		}
		fos.close();
		is.close();
		//4.显示
		Toast.makeText(this, "保存完成", 0).show();
	}
2.读取数据 

	public void read(View v) {// /data/data/packageName/files/logo.png
		//1.得到图片文件路径
			///data/data/packageName/files
		String filesPath = getFilesDir().getAbsolutePath();
		String imagePath = filesPath + "/logo.png";
		//2.读取加载图片文件得到bitmap对象
		Bitmap bitmap = BitmapFactory.decodeFile(imagePath);
		//3.将其设置到imgeView中显示 
		iv_if.setImageBitmap(bitmap);
	}

三, SD卡外部file存储

应用运行用到的数据文件(如图片)可以保存到sd卡中
文件类型: 任意
数据保存的路径: 
路径1: /storage/sdcard/Android/data/packageName/files/
路径2: /storage/sdcard/xxx/
路径1 :其它应用可以访问,应用卸载时删除
路径2 : 其它应用可以访问, 应用卸载时不会删除
必须保证sd卡挂载在手机上才能读写, 否则不能操作

Environment :  操作SD卡的工具类
得到SD卡的状态:Environment.getExternalStorageState() 
得到SD卡的路径:Environment.getExternalStorageDirectory()
SD卡可读写的挂载状态值:Environment.MEDIA_MOUNTED
context. getExternalFilesDir():   得到/mnt/sdcard/Android/data/pageckage_name/files/xxx.txt
操作SD卡的权限: android.permission.WRITE_EXTERNAL_STORAGE

路径1:
1.保存数据 

	public void save(View v) throws IOException {
		//1.判断sd卡状态,如果是挂载的状态才继续,否则提示
		if(Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)){
			//2.读取输入的文件名\内容;
			String fileName = et_of_name.getText().toString();
			String content = et_of_content.getText().toString();
			//3.得到指定文件的OutputStream
				//1).得到sd卡下的files路径
			String filesPath = getExternalFilesDir(null).getAbsolutePath();
				//2).组成完整路径
			String filePath = filesPath + "/" + fileName;
				//3).创建FileOutputStream
			FileOutputStream fos = new FileOutputStream(filePath);
			//4.写数据
			fos.write(content.getBytes("utf-8"));
			fos.close();
			//5.提示
			Toast.makeText(this, "保存完成", 0).show();
		}else{
			Toast.makeText(this, "sd卡没有挂载", 0).show();
		}
	}

2.读取数据

	public void read(View v) throws IOException {
		//1.判断sd卡状态,如果是挂载的状态才继续,否则提示
		if(Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)){
			//2.读取输入的文件名\内容;
			String fileName = et_of_name.getText().toString();
			//3.得到指定文件的OutputStream
				//1).得到sd卡下的files路径
			String filesPath = getExternalFilesDir(null).getAbsolutePath();
				//2).组成完整路径
			String filePath = filesPath + "/" + fileName;
				//3).创建FileInputStream
			FileInputStream fis = new FileInputStream(filePath);
			//4.写数据
			ByteArrayOutputStream baos = new ByteArrayOutputStream();
			byte[] buffer = new byte[1024];
			int len = -1;
			while((len=fis.read(buffer))!=-1){
				baos.write(buffer,0,len);
			}
			String content = baos.toString();
			
			//5.显示
			et_of_content.setText(content);
		}else{
			Toast.makeText(this, "sd卡没有挂载", 0).show();
		}
	}

路径2:
1.保存数据 

	// /storage/sdcard/atguigu/xxx.txt
	public void save2(View v) throws Exception {
		//1.判断sd卡状态,如果是挂载的状态才继续,否则提示
		if(Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)){
			//2.读取输入的文件名\内容;
			String fileName = et_of_name.getText().toString();
			String content = et_of_content.getText().toString();
			//3.得到指定文件的OutputStream
				//1)./storage/sdcard/
			String sdPath = Environment.getExternalStorageDirectory().getAbsolutePath();
				//2)./storage/sdcard/atguigu/(创建文件夹)
			File file = new File(sdPath+"/atguigu");
			if(!file.exists()){
				file.mkdirs();//创建文件夹
			}
				//3)./storage/sdcard/atguigu/xxx.txt
			String filePath = sdPath+"/atguigu/"+fileName;
				//4).创建输出流
			FileOutputStream fos = new FileOutputStream(filePath);
			//4.写数据
			fos.write(content.getBytes("utf-8"));
			fos.close();
			//5.提示
			Toast.makeText(this, "保存完成", 0).show();
		}else{
			Toast.makeText(this, "sd卡没有挂载", 0).show();
		}
	}
2.读取数据 
	public void read2(View v) throws Exception {
		//1.判断sd卡状态,如果是挂载的状态才继续,否则提示
		if(Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)){
			//2.读取输入的文件名\内容;
			String fileName = et_of_name.getText().toString();
			//3.得到指定文件的IntputStream
				//1)./storage/sdcard/
			String sdPath = Environment.getExternalStorageDirectory().getAbsolutePath();
			String filePath=sdPath+"/atguigu/"+fileName;
				//3).创建FileInputStream
			FileInputStream fis = new FileInputStream(filePath);
			//4.读取数据,成String
			ByteArrayOutputStream baos = new ByteArrayOutputStream();
			byte[] buffer = new byte[1024];
			int len = -1;
			while((len=fis.read(buffer))!=-1){
				baos.write(buffer,0,len);
			}
			String content = baos.toString();
			fis.close();
			//5.显示
			et_of_content.setText(content);
		}else{
			Toast.makeText(this, "sd卡没有挂载", 0).show();
		}		
	}

四,SQLite数据库存储

1)说明

应用运行需要保存一系列有一定结构的数据, 比如说公司员工信息
文件类型: .db
数据保存的路径: /data/data/projectPackage/databases/xxx.db
默认情况下其它应用不能访问, 当前应用可以通过ContentProvider提供其它应用操作
应用卸载时会删除此数据

SQLite (http://www.sqlite.org/),是一款轻型的关系型数据库服务器, 移动设备的数据库存储都使用SQLite,

 2)它的特点: 
安装文件小: 最小只有几百K, Android系统已经安装
支持多操作系统: Android, WP, IOS, Windows, Linux等
支持多语言: 比如 Java 、 PHP、C#等. 
处理速度快:  处理速度比Mysql, Oracle, SqlServer都要快(数据量不是特别大)
Sqlite中的一个数据库就是一个.db文件(本质上.db的后缀都可以不指定)

3)Sqlite数据库命令行

adb shell  进入系统根目录
cd data/data/…/databases : 进入包含数据库文件的文件夹下
sqlite3 contacts2.db : 使用sqlite3命令连接指定的数据库文件, 进入连接模式
 .help : 查看命令列表
.tables : 查看所有表的列表
执行insert/delete/update/select语句
.exit : 退出数据库连接模式
Ctrl + C : 直接退出sell模式

4)SQLite支持的数据类型

INT/INTEGER : 整数
FLOAT/DOUBLE : 小数
CHAR/VARCHAR/TEXT : 字符串文本
BLOB : 文件
DATE/ DATETIME : 日期/日期时间
5)Sqlite的CRUD语句

/*插入*/
INSERT INTO employee (name,salary,birthday) VALUES('Tom', 8000, '1988-09-21');
/*删除*/
DELETE FROM employee WHERE _id=2 
/*更新*/
UPDATE employee SET name='Jack',salary=salary+1000 WHERE _id=1
/*查找*/
SELECT * FROM employee where _id=3

6)SQLiteOpenHelper: 数据库操作的抽象帮助类

   SQLiteOpenHelper(Context context, String name, 
           CursorFactory factory, int version) : 构造方法, 指定数据库文件名和版本号
      abstract void onCreate(SQLiteDatabase db) : 用于创建表
      abstract void onUpgrade() : 用于版本更新
      SqliteDatabase getReadableDatabase() : 得到数据库连接
7)SqliteDatabase: 代表与数据库的连接的类

long insert(): 用于执行insert SQL, 返回id值
       int update(): 用于执行update SQL
       int delete(): 用于执行delete SQL
       Cursor query(): 用于执行select SQL, 返回包含查询结果数据的Cursor
       void execSql(sql) : 执行sql语句
     
       beginTransaction(): 开启事务
       setTransactionSuccessful(): 设置事务是成功的
       endTransaction(): 结束事务, 可能提交事务或回滚事务
       openDatabase(String path, CursorFactory factory, int flags):  得到数据库连接

8)Cursor : 包含所有查询结果记录的结果集对象(光标,游标)

int getCount() : 匹配的总记录数
boolean moveToNext() : 将游标移动到下一条记录的前面
Xxx getXxx(columnIndex) : 根据字段下标得到对应值
int getColumnIndex(columnname): 根据字段名得到对应的下标

数据库操作的帮助类

package com.example.activitydemo;

import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteDatabase.CursorFactory;
import android.database.sqlite.SQLiteOpenHelper;
import android.util.Log;
/**
 * 数据库操作的帮助类
 * @author Xiaocici
 *
 */
public class DBHelper extends SQLiteOpenHelper {

	public DBHelper(Context context,int version) {
		super(context,"atguigu",null, version);
		// TODO Auto-generated constructor stub
	}

	/**
	 * 什么时候才会创建数据库文件?
	 *  1)数据库文件不存在
	 *  2)
	 * 
	 * 当数据库文件创建的时候调用
	 * 建表
	 * 插入一些初始化数据
	 */
	@Override
	public void onCreate(SQLiteDatabase db) {
		Log.e("TAG", "DBHelper create");
		//建表
		String sql = "create table person( _id integer primary key autoincrement, name varchar,age int)";
		db.execSQL(sql);
		//插入一些初始化数据
		db.execSQL("insert into person(name,age) values( 'Tom1',11)");
		db.execSQL("insert into person(name,age) values( 'Tom2',12)");
		db.execSQL("insert into person(name,age) values( 'Tom3',13)");
	}

	//当传入的版本号大于数据库的版本号时调用
	@Override
	public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
		Log.e("TAG", "DBHelper onUpgrade");

	}

}
创建库

	public void testCreateDB(View v){
		DBHelper dbHelper = new DBHelper(this, 1);
		
		//获取连接
		SQLiteDatabase database = dbHelper.getReadableDatabase();
		Toast.makeText(this, "创建数据库", 0).show();
	}
更新库
public void testUpdateDB(View v){
		DBHelper dbHelper = new DBHelper(this, 2);
		//获取连接
		SQLiteDatabase database = dbHelper.getReadableDatabase();
		Toast.makeText(this, "更新数据库", 0).show();
	}
添加记录
	public void testInsert(View v){
		//1.得到连接
		DBHelper dbHelper = new DBHelper(this, 2);
		SQLiteDatabase database = dbHelper.getReadableDatabase();
		//2.执行insert insert into person(name,age) values('Tom',12)
		ContentValues values = new ContentValues();
		values.put("name", "Tom");
		values.put("age", 12);
		long id = database.insert("person", null, values);
		//3.关闭
		database.close();
		//4.提示
		Toast.makeText(this, "id=" + id, 0).show();
	}
更新
	public void testUpdate(View v){
		DBHelper dbHelper = new DBHelper(this, 2);
		SQLiteDatabase database = dbHelper.getReadableDatabase();
		//执行Update update person set name=Jack,age=13 where _id=4
		ContentValues values = new ContentValues();
		values.put("name", "Jack");
		values.put("age", 13);
		int updateCount = database.update("person", values , "_id=?", new String[]{"4"});
		database.close();
		Toast.makeText(this, "updateCount=" + updateCount, 0).show();
	}

删除

	public void testDelete(View v){
		//1.得到连接
		DBHelper dbHelper = new DBHelper(this, 2);
		SQLiteDatabase database = dbHelper.getReadableDatabase();
		//2.执行delete delete from person where _id=2
		int deleteCount = database.delete("person", "_id=2", null);
		//3.关闭
		database.close();
		//4.提示
		Toast.makeText(this, "deleteCount=" + deleteCount, 0).show();
	}

查询
	public void testQuery(View v){
		//1.得到连接
		DBHelper dbHelper = new DBHelper(this, 2);
		SQLiteDatabase database = dbHelper.getReadableDatabase();
		//2.执行query select * from person
		Cursor cursor = database.query("person", null, null, null, null, null, null);
		//Cursor cursor = database.query("person", null, "_id=?", new String[]{"3"}, null, null, null);
		//得到总匹配数
		int count = cursor.getCount();
		//取出cursor中的所有数据
		while(cursor.moveToNext()){
			//_id
			int id = cursor.getInt(0);
			//name
			String name = cursor.getString(1);
			//age
			int age = cursor.getInt(cursor.getColumnIndex("age"));
			Log.e("TAG", id+"-" + name + "-" + age);
			
		}
		//3.关闭
		cursor.close();
		database.close();
		//4.提示
		Toast.makeText(this, "count=" + count, 0).show();
		
	}

	/*
	 *测试事务处理
	 *update person set age=15 where _id=1
	 *update person set age=17 where _id=3
	 *
	 *一个功能中对数据库进行的多个操作,要么都成功,要么都失败
	 *事务处理的3步:
	 *1.开启事务(获取连接后)
	 *2.设置事务成功(在全部正常执行完后)
	 *3.结束事务(finally)
	 */
	public void testTransaction(View v) {
		SQLiteDatabase database = null;
		try{
			// 得到连接
			DBHelper dbHelper = new DBHelper(this, 2);
			database = dbHelper.getReadableDatabase();
			
			//1.开启事务(获取连接后)
			database.beginTransaction();
			
			// 执行update update person set age=15 where _id=1
			ContentValues values = new ContentValues();
			values.put("age", 15);
			int updateCount = database.update("person", values , "_id=?", new String[]{"1"});
			Log.e("Tag","updateCount="+ updateCount);
			
			//出了异常
			boolean flag=true;
			if(flag){
				throw new RuntimeException("出异常啦!!!");
			}
			
			// 执行update update person set age=17 where _id=3
			values = new ContentValues();
			values.put("age", 17);
			int updateCount2 = database.update("person", values , "_id=?", new String[]{"3"});
			Log.e("Tag", "updateCount2=" + updateCount2);
			
			//2.设置事务成功(在全部正常执行完后)
			database.setTransactionSuccessful();
			
			//关閉
			database.close();
		}catch(Exception e){
			e.printStackTrace();
			Toast.makeText(this, "出异常了~~", 0).show();
		}finally{
			//3.结束事务(finally)
			if(database==null){
				database.endTransaction();
				database.close();
			}
		}
	}
五.远程服务器存储

太长了,接下一篇


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值