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(); // 结束事务 } }
。。
相关推荐
这个程序基于郭炜老师的畅销书《第一行代码》中的最后一个示例,它利用了百度API Store提供的天气查询服务,同时地区数据存储在SQLite数据库中。下面我们将深入探讨这个示例所涵盖的关键知识点。 首先,我们要了解*...
【标题】:“第一行代码Android学习练习代码7” 在Android开发中,“第一行代码”是一本广受欢迎的入门书籍,作者郭霖通过简洁易懂的方式介绍了Android开发的基础知识。这个练习代码7应该是针对书中第六章内容的...
《第一行代码——Android(第3版)》是郭霖老师撰写的一本广受欢迎的Android入门书籍,旨在帮助初学者快速掌握Android应用开发的基本技能。这本书的资源压缩包包含了丰富的学习资料,对于想要深入理解Android开发的...
《第一行代码Java》是一本深受初学者喜爱的编程入门书籍,主要针对Java语言进行讲解。这本书通过简单易懂的方式,引导读者从零开始学习Java编程。配套的源代码资源对于学习过程至关重要,因为它提供了实际操作的例子...
【标题】"第一行代码Android学习练习代码4" 涉及的是Android应用程序开发的学习实践,这个练习可能基于郭神(郭霖)所著的畅销书籍《第一行代码——Android》。这本书是许多初学者入门Android开发的重要参考资料,它...
《第一行Android代码(第二版)》是一本深入浅出的Android编程入门书籍,它旨在帮助初学者快速理解和掌握Android应用开发的基本技能。书中通过丰富的实例和详细的解释,引导读者从零开始,逐步构建自己的第一个...
【标题】"第一行代码Android学习练习代码9" 涉及的是Android开发中的实践环节,这通常是基于郭文静的畅销书《第一行代码——Android》中的第九个练习项目。这本书是Android初学者入门的经典教材,通过实际的编程练习...
《第一行代码——Android》涵盖了许多主题,包括Android开发环境的搭建、基本UI组件的使用、数据存储、网络通信、多媒体处理等。如果这个练习是第八个,那么它可能建立在前七章的知识基础上,例如已经学习了如何创建...
《第一行代码-Android 源代码》是郭霖撰写的一本面向初学者的Android编程书籍,这本书通过实例引导读者逐步了解和掌握Android应用开发。源代码压缩包提供了书中所有示例程序的完整代码,方便读者实践和学习。以下是...
《第一行代码Android》是郭霖撰写的一本经典Android入门书籍,深受初学者喜爱。书中的练习代码12,很可能是针对某个特定章节的实践项目或编程练习,旨在帮助读者巩固理论知识,提升实际编程技能。这个压缩包可能包含...
《第一行Android代码》课件:第六章 数据存储全方案-详解持久化技术.pptx
《第一行代码:Android》是郭霖先生撰写的一本经典的Android入门书籍,书中通过实例讲解了Android开发的基础知识。在书中的最后一个实践项目,作者带领读者实现了一个名为“酷欧天气”的应用。这个项目旨在帮助读者...
《Android第一行代码笔记》是针对初学者的Android开发指南,涵盖了从基础知识到实际应用的全方位内容。在学习Android开发的过程中,"第一行代码"往往代表着编程旅程的起点,这本笔记将帮助读者逐步理解并掌握这个...
1. **Android Studio入门**:Android Studio是Android开发的官方集成开发环境(IDE),书中会介绍如何下载、安装和配置Android Studio,以及创建第一个"Hello, World!"应用。 2. **AndroidManifest.xml**:每个...
《第二行代码》是Android开发领域的一本经典书籍,作者通过深入浅出的方式,引导读者逐步掌握Android应用开发的核心技术。在第11章中,作者通常会介绍一些高级话题或者关键概念,以帮助开发者提升技能。源码是学习...
这本书以生动的语言和丰富的实例,引导读者从“第一行代码”顺利过渡到“第二行代码”,掌握实际的编程技能。在提供的压缩包“郭霖第二行代码---源代码.rar”中,包含了作者为书中的示例程序编写的源代码,这对于...
共享单车数据存储系统代码 java共享单车数据存储系统代码 基于springboot的共享单车数据存储系统代码 1、共享单车数据存储系统的技术栈、环境、工具、软件: ① 系统环境:Windows/Mac ② 开发语言:Java ③ 框架:...
共享单车数据存储-共享单车数据存储系统-共享单车数据存储系统源码-共享单车数据存储管理系统-共享单车数据存储管理系统java代码-共享单车数据存储系统设计与实现-基于springboot的共享单车数据存储系统-基于Web的...