`
uule
  • 浏览: 6351583 次
  • 性别: Icon_minigender_1
  • 来自: 一片神奇的土地
社区版块
存档分类
最新评论

《第一行代码》数据存储

 
阅读更多

 

11、数据存储

 

将数据存储到文件中

openFileOutput ()方法,可以用于将数据存储到指定的文件中。

这个方法接收两个参数,第一个参数是文件名,在文件创建的时候使用的就是这个名称,注意这里指定的文件名不可以包含路径,因为所有的文件都是默认存储到/data/data/<packagename>/files/ 目 录 下 的 。 

 

        第 二 个 参 数 是 文 件 的 操 作 模 式 , 主 要 有 两 种 模 式 可 选 ,MODE_PRIVATE 和 MODE_APPEND

        MODE_PRIVATE 是默认的操作模式,

表示当指定同样文件名的时候,所写入的内容将会覆盖原文件中的内容,

        MODE_APPEND 

则表示如果该文件已存在就往文件里面追加内容,不存在就创建新文件。

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

 

从文件中读取数据

openFileOutput()只接收一个参数,即要读取的文件名,然后系统会自动到/data/data/<package name>/files/目录下去加载这个文件,并返回一个FileInputStream 对象,得到了这个对象之后再通过 Java 流的方式就可以将数据读取出来了。

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();
	}

 

【SharedPreferences 存储】

使用键值对的方式来存储数据

 

获取到SharedPreferences对象

三种方式:

1、Context 类中的 getSharedPreferences()方法

 

此方法接收两个参数,第一个参数用于指定 SharedPreferences 文件的名称,如果指定的文件不存在则会创建一个,SharedPreferences 文件都是存放在/data/data/<packagename>/shared_prefs/目录下的。

第二个参数用于指定操作模式,主要有两种模式可以选择,MODE_PRIVATE 和 MODE_MULTI_PROCESS。

MODE_PRIVATE 仍然是默认的操作模式,和直接传入 0 效果是相同的,表示只有当前的应用程序才可以对这个SharedPreferences文件进行读写。

MODE_MULTI_PROCESS 则一般是用于会有多个进程中对同一个 SharedPreferences 文件进行读写的情况。

 

2、Activity 类中的 getPreferences()方法

这个方法和 Context 中的 getSharedPreferences()方法很相似,不过它只接收一个操作模式参数,因为使用这个方法时会自动将当前活动的类名作为 SharedPreferences 的文件名。

 

3、PreferenceManager 类中的 getDefaultSharedPreferences()方法

这是一个静态方法,它接收一个 Context 参数,并自动使用当前应用程序的包名作为前缀来命名 SharedPreferences 文件。

 

 

向 SharedPreferences 文件中存储数据了,

主要可以分为三步实现:

1. 调用 SharedPreferences 对象的 edit()方法来获取一个 SharedPreferences.Editor 对象。

2. 向 SharedPreferences.Editor 对象中添加数据,

比如添加一个布尔型数据就使用putBoolean 方法,添加一个字符串则使用 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();

 

生成了一个 data.xml文件

 

从SharedPreferences 中读取数据

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

 

【SQLite 数据库存储】

 

Android 系统内置了数据库的!

SQLite 是一款轻量级的关系型数据库,它的运算速度非常快,占用资源很少,通常只需要几百 K 的内存就足够了,因而特别适合在移动设备上使用。

SQLite不仅支持标准的 SQL 语法,还遵循了数据库的 ACID 事务

 

创建数据库

integer 表示整型,real 表示浮点型,text 表示文本类型,blob 表示二进制类型

 

SQLiteOpenHelper 帮助类,借助这个类就可以非常简单地对数据库进行创建和升级

SQLiteOpenHelper 是一个抽象类,SQLiteOpenHelper 中有两个抽象方法,分别是onCreate()和 onUpgrade()

 

SQLiteOpenHelper 中 还 有 两 个 非 常 重 要 的 实 例 方 法 , getReadableDatabase() 和getWritableDatabase()。

这两个方法都可以创建或打开一个现有的数据库(如果数据库已存在则直接打开,否则创建一个新的数据库),并返回一个可对数据库进行读写操作的对象。

不同的是,当数据库不可写入的时候(如磁盘空间已满)getReadableDatabase()方法返回的对象将以只读的方式去打开数据库,而 getWritableDatabase()方法则将出现异常

 

 

构造方法中接收四个参数,

第一个参数是 Context,这个没什么好说的,必须要有它才能对数据库进行操作。

第二个参数是数据库名,创建数据库时使用的就是这里指定的名称。

第三个参数允许我们在查询数据的时候返回一个自定义的 Cursor,一般都是传入 null。

第 四 个 参 数 表 示 当 前 数 据 库 的 版 本 号 , 可 用 于 对 数 据 库 进 行 升 级 操 作 。

 

数据库文件会存放在/data/data/<package 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);
			mContext = context;
		}
		
		@Override
		public void onCreate(SQLiteDatabase db) {
			db.execSQL(CREATE_BOOK);
			Toast.makeText(mContext, "Create succeeded", Toast.LENGTH_SHORT).show();
		}
		@Override
		public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
		}
	}

//MainActivity:

	dbHelper = new MyDatabaseHelper(this, "BookStore.db", null, 1);
	Button createDatabase = (Button) findViewById(R.id.create_database);
	createDatabase.setOnClickListener(new OnClickListener() {
		@Override
		public void onClick(View v) {
			dbHelper.getWritableDatabase();
		}
	});

 

输入 adb shell,就会进入到设备的控制台,使用 cd 命令进行到/data/data/com.example.databasetest/databases/目录下,并使用 ls 命令查看到该目录里的文件

 

打开数据库:

sqlite3 数据库全名(sqlite3 Book.db)

 

查看数据库表:

键入.table 命令

 

查看建表语句

.schema

 

退出数据库的编辑

键入.exit 或.quit

 

 

升级数据库

1、

public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
		//这种方式会让老用户数据丢失
		db.execSQL("drop table if exists Book");
		db.execSQL("drop table if exists Category");
		
		//增加版本号判断
		switch (oldVersion) {
			case 1:
				db.execSQL(CREATE_CATEGORY);
			case 2:
				db.execSQL("alter table Book add column category_id integer");
			default:
		}
		
		onCreate(db);
	}	
	

 

细节:

switch 中每一个 case 的最后都是没有使用 break 的,为什么要这么做呢?这是为了保证在跨版本升级的时候,每一次的数据库修改都能被全部执行到

 

2、让 onUpgrade()方法执行

还记得 SQLiteOpenHelper 的构造方法里接收的第四个参数吗?它表示当前数据库的版本号,之前我们传入的是 1,现在只要传入一个比 1 大的数,就可以让 onUpgrade()方法得到执行了

 

添加数据:

 

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 Lost Symbol");
	values.put("author", "Dan Brown");
	values.put("pages", 510);
	values.put("price", 19.95);
	db.insert("Book", null, values); // 插入第二条数据
	
	
	或:
	db.execSQL("insert into Book (name, author, pages, price) values(?, ?, ?, ?)",
		new String[] { "The Da Vinci Code", "Dan Brown", "454", "16.96" });

  

更新数据:

 

ContentValues values = new ContentValues();
	values.put("price", 10.99);
	db.update("Book", values, "name = ?", new String[] { "The DaVinci Code" });
	
	db.execSQL("update Book set price = ? where name = ?", new String[] { "10.99",
		"The Da Vinci Code" });

 

删除数据:

 

SQLiteDatabase db = dbHelper.getWritableDatabase();
db.delete("Book", "pages > ?", new String[] { "500" });

或
db.execSQL("delete from Book where pages > ?", new String[] { "500" });	

 

查询数据:

query()方法用于对数据进行查询。

 

   

这个方法的参数非常复杂,最短的一个方法重载也需要传入七个参数。

第一个参数不用说,当然还是表名,表示我们希望从哪张表中查询数据。

第二个参数用于指定去查询哪几列,如果不指定则默认查询所有列。

第三、第四个参数用于去约束查询某一行或某几行的数据,不指定则默认是查询所有行的数据。

第五个参数用于指定需要去 group by 的列,不指定则表示不对查询结果进行 group by 操作。

第六个参数用于对 group by 之后的数据进行进一步的过滤,不指定则表示不进行过滤。

第七个参数用于指定查询结果的排序方式,不指定则表示使用默认的排序方式。

 

SQLiteDatabase db = dbHelper.getWritableDatabase();
	Cursor cursor = 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();

   

db.rawQuery("select * from Book", null);

可以看到,除了查询数据的时候调用的是 SQLiteDatabase 的 rawQuery()方法,其他的操作都是调用的 execSQL()方法。

 

事务:

SQLiteDatabase db = dbHelper.getWritableDatabase();
	db.beginTransaction(); // 开启事务
	
	try {
		db.delete("Book", null, null);
		if (true) {
			// 在这里手动抛出一个异常,让事务失败
			throw new NullPointerException();
		}
		ContentValues values = new ContentValues();
		values.put("name", "Game of Thrones");
		values.put("author", "George Martin");
		values.put("pages", 720);
		values.put("price", 20.85);
		db.insert("Book", null, values);
		
		db.setTransactionSuccessful(); // 事务已经执行成功
		
	} catch (Exception e) {
		e.printStackTrace();
	} finally {
		db.endTransaction(); // 结束事务
	}
	}
	

 

。。

  • 大小: 19.1 KB
分享到:
评论

相关推荐

    第一行代码天气示例

    这个程序基于郭炜老师的畅销书《第一行代码》中的最后一个示例,它利用了百度API Store提供的天气查询服务,同时地区数据存储在SQLite数据库中。下面我们将深入探讨这个示例所涵盖的关键知识点。 首先,我们要了解*...

    第一行代码Android学习练习代码7

    【标题】:“第一行代码Android学习练习代码7” 在Android开发中,“第一行代码”是一本广受欢迎的入门书籍,作者郭霖通过简洁易懂的方式介绍了Android开发的基础知识。这个练习代码7应该是针对书中第六章内容的...

    第一行代码资源.zip

    《第一行代码——Android(第3版)》是郭霖老师撰写的一本广受欢迎的Android入门书籍,旨在帮助初学者快速掌握Android应用开发的基本技能。这本书的资源压缩包包含了丰富的学习资料,对于想要深入理解Android开发的...

    第一行代码Java源代码等配套资源

    《第一行代码Java》是一本深受初学者喜爱的编程入门书籍,主要针对Java语言进行讲解。这本书通过简单易懂的方式,引导读者从零开始学习Java编程。配套的源代码资源对于学习过程至关重要,因为它提供了实际操作的例子...

    第一行Android代码(第二版)源码

    《第一行Android代码(第二版)》是一本深入浅出的Android编程入门书籍,它旨在帮助初学者快速理解和掌握Android应用开发的基本技能。书中通过丰富的实例和详细的解释,引导读者从零开始,逐步构建自己的第一个...

    第一行代码Android学习练习代码4

    【标题】"第一行代码Android学习练习代码4" 涉及的是Android应用程序开发的学习实践,这个练习可能基于郭神(郭霖)所著的畅销书籍《第一行代码——Android》。这本书是许多初学者入门Android开发的重要参考资料,它...

    第一行代码Android学习练习代码9

    【标题】"第一行代码Android学习练习代码9" 涉及的是Android开发中的实践环节,这通常是基于郭文静的畅销书《第一行代码——Android》中的第九个练习项目。这本书是Android初学者入门的经典教材,通过实际的编程练习...

    第一行代码Android学习练习代码8

    《第一行代码——Android》涵盖了许多主题,包括Android开发环境的搭建、基本UI组件的使用、数据存储、网络通信、多媒体处理等。如果这个练习是第八个,那么它可能建立在前七章的知识基础上,例如已经学习了如何创建...

    第一行代码-Android 源代码

    《第一行代码-Android 源代码》是郭霖撰写的一本面向初学者的Android编程书籍,这本书通过实例引导读者逐步了解和掌握Android应用开发。源代码压缩包提供了书中所有示例程序的完整代码,方便读者实践和学习。以下是...

    第一行代码Android学习练习代码12

    《第一行代码Android》是郭霖撰写的一本经典Android入门书籍,深受初学者喜爱。书中的练习代码12,很可能是针对某个特定章节的实践项目或编程练习,旨在帮助读者巩固理论知识,提升实际编程技能。这个压缩包可能包含...

    《第一行Android代码》课件:第六章 数据存储全方案-详解持久化技术.pptx

    《第一行Android代码》课件:第六章 数据存储全方案-详解持久化技术.pptx

    《第一行代码》酷欧天气(kotlin版)

    《第一行代码:Android》是郭霖先生撰写的一本经典的Android入门书籍,书中通过实例讲解了Android开发的基础知识。在书中的最后一个实践项目,作者带领读者实现了一个名为“酷欧天气”的应用。这个项目旨在帮助读者...

    android第一行代码笔记

    《Android第一行代码笔记》是针对初学者的Android开发指南,涵盖了从基础知识到实际应用的全方位内容。在学习Android开发的过程中,"第一行代码"往往代表着编程旅程的起点,这本笔记将帮助读者逐步理解并掌握这个...

    Android第二行代码(郭霖全书源代码)

    1. **Android Studio入门**:Android Studio是Android开发的官方集成开发环境(IDE),书中会介绍如何下载、安装和配置Android Studio,以及创建第一个"Hello, World!"应用。 2. **AndroidManifest.xml**:每个...

    《第二行代码》11章源码

    《第二行代码》是Android开发领域的一本经典书籍,作者通过深入浅出的方式,引导读者逐步掌握Android应用开发的核心技术。在第11章中,作者通常会介绍一些高级话题或者关键概念,以帮助开发者提升技能。源码是学习...

    郭霖第二行代码---源代码.rar

    这本书以生动的语言和丰富的实例,引导读者从“第一行代码”顺利过渡到“第二行代码”,掌握实际的编程技能。在提供的压缩包“郭霖第二行代码---源代码.rar”中,包含了作者为书中的示例程序编写的源代码,这对于...

    共享单车数据存储系统代码 java共享单车数据存储系统代码

    共享单车数据存储系统代码 java共享单车数据存储系统代码 基于springboot的共享单车数据存储系统代码 1、共享单车数据存储系统的技术栈、环境、工具、软件: ① 系统环境:Windows/Mac ② 开发语言:Java ③ 框架:...

    共享单车数据存储-共享单车数据存储系统-共享单车数据存储系统源码-共享单车数据存储管理系统-共享单车数据存储管理系统java代码

    共享单车数据存储-共享单车数据存储系统-共享单车数据存储系统源码-共享单车数据存储管理系统-共享单车数据存储管理系统java代码-共享单车数据存储系统设计与实现-基于springboot的共享单车数据存储系统-基于Web的...

Global site tag (gtag.js) - Google Analytics