在Android中读写文件
- RAM:运行内存,相当于电脑的内存
- ROM:内部存储空间,相当于电脑的硬盘
- Android手机必须有的
- SD卡:外部存储空间,相当于电脑的移动硬盘
- 不是必须的
- 现在手机自带的空间都属于外部存储,然后手机基本内部外部共享同一个存储设备
内部读写
内部存储路径
- 所有安装至手机的应用都会在data/data目录下生成一个包名文件夹,这个文件夹就是内部存储的路径
- 应用只能在自己的包名文件夹中读写文件
写
File file = new File("data/data/text/text.txt");
//返回一个File对象,封装的路径是data/data/text/files
//File file = new File(getFilesDir(), "text.txt");
try {
FileOutputStream fos = new FileOutputStream(file);
fos.write((name + "&&" + pass).getBytes());
fos.close();
} catch (Exception e) {
e.printStackTrace();
}
“data/data/text/text.txt”在android studio 点击目录栏角Monitor选择使用的虚拟机,右边的File Explorer下面。
读
File file = new File("data/data/text/text.txt");
//返回一个File对象,封装的路径是data/data/text/files
//File file = new File(getFilesDir(), "text.txt");
try {
FileInputStream fis = new FileInputStream(file);
//把字节流转换成字符流
BufferedReader br = new BufferedReader(new InputStreamReader(fis));
//读取文件中的文本
String text = br.readLine();
String s[] = text.split("&&");
//给输入框设置文本
et_name.setText(s[0]);
et_pass.setText(s[1]);
} catch (Exception e) {
e.printStackTrace();
}
外部读写
外部存储路径
- 2.2之前:sdcard
- 2.2~4.2:mnt/sdcard
- 4.3开始:storage/sdcard
外部读写和内部读写的区别仅仅是路径
//返回一个File对象,封装了外部存储的真实路径
File file = new File(Environment.getExternalStorageDirectory(), "info.txt");
判断SD卡是否可用
//MEDIA_REMOVED:sd卡不存在
//MEDIA_UNMOUNTED:sd卡存在,但是没有挂载
//MEDIA_CHECKING:sd卡正在遍历
//MEDIA_MOUNTED:sd卡可用
//MEDIA_MOUNTED_READ_ONLY:sd卡可用,但是只读 if(Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)){
}
文件存储权限
- 每一个应用都是一个独立的用户
- drwxrwxrwx
- 第一个字母d
- d:表示文件夹
- -:表示文件
- 第一组rwx:文件拥有者(owner)的权限
- r:读
- w:写
- x:执行execute
- 第二组rwx:与文件拥有者同一用户组的用户(grouper)
- 第三组rwx:其他用户(other)的权限
SharedPreferences
- 以键值对的形式保存数据
- 适合存放零散简单的数据
- 原理其实是生成xml文件去保存
写
//获取sharedpreferences
SharedPreferences sp = getSharedPreferences(“info”, MODE_PRIVATE);
//获取编辑器
Editor ed = sp.edit();
ed.putString(“name”, name);
ed.putString(“pass”, pass);
//提交
ed.commit();
读
SharedPreferences sp = getSharedPreferences(“info”, MODE_PRIVATE);
String name = sp.getString(“name”, “”);
String pass = sp.getString(“pass”, “”);
et_name.setText(name);
et_pass.setText(pass);
SQLite
概念
SQLite,是一款轻型的数据库,是遵守ACID的关系型数据库管理系统,它包含在一个相对小的C库中。它是D.RichardHipp建立的公有领域项目。它的设计目标是嵌入式的,而且目前已经在很多嵌入式产品中使用了它,它占用资源非常的低,在嵌入式设备中,可能只需要几百K的内存就够了。它能够支持Windows/Linux/Unix等等主流的操作系统,同时能够跟很多程序语言相结合,比如 Tcl、C#、PHP、Java等,还有ODBC接口,同样比起Mysql、PostgreSQL这两款开源的世界著名数据库管理系统来讲,它的处理速度比他们都快。
工作原理
不同于常见的客户-服务器范例,SQLite引擎不是个程序与之通信的独立进程,而是连接到程序中成为它的一个主要部分。所以主要的通信协议是在编程语言内的直接API调用。这在消耗总量、延迟时间和整体简单性上有积极的作用。整个数据库(定义、表、索引和数据本身)都在宿主主机上存储在一个单一的文件中。它的简单的设计是通过在开始一个事务的时候锁定整个数据文件而完成的
创建
- 创建数据库需要使用的api:SQLiteOpenHelper
通常我们会新建一个数据库打开类继承SQLiteOpenHelper,继承之后必须有一个构造方法和两个公有方法。
public class MyOpenHelper extends SQLiteOpenHelper {
public MyOpenHelper(Context context) {
//arg0:传进来的上下文
//arg1:数据库文件名字
//arg2:游标工厂,游标等同于结果集,传null使用默认工厂
//arg3:版本,不能小于1,用于升级
super(context, "people.db", null, 1);
}
//创建数据库时调用
@Override
public void onCreate(SQLiteDatabase db) {
//创建表
db.execSQL("create table person(_id integer primary key autoincrement, name char(10), phone char(20), salary integer(10))");
}
//升级数据库时调用
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
System.out.println("数据库升级");
}
}
增删改查
谷歌为了方便我们实现增删改查功能,有集成的api可以给我们使用。
public class Test extends AndroidTestCase{
private MyOpenHelper oh;
private SQLiteDatabase db;
public void test(){
//获取虚拟上下文
MyOpenHelper oh = new MyOpenHelper(getContext());
//如果数据库不存在,先创建,再打开,如果存在,就直接打开
SQLiteDatabase db = oh.getWritableDatabase();
}
//测试方法执行前调用,只是为了初始化工厂和数据库,可没有
@Override
protected void setUp() throws Exception {
super.setUp();
oh = new MyOpenHelper(getContext());
db = oh.getWritableDatabase();
}
//测试方法执行后调用,只是为了关流,可没有
@Override
protected void tearDown() throws Exception {
super.tearDown();
db.close();
}
//增
public void insert(){
db.execSQL("insert into person(name, phone, salary) values (?, ?, ?)", new Object[]{"刘备", "138438", 13000});
db.execSQL("insert into person(name, phone, salary) values (?, ?, ?)", new Object[]{"关羽", "138438", 13000});
}
//删
public void delete(){
db.execSQL("delete from person where name = ?", new Object[]{"刘备"});
}
//改
public void update(){
db.execSQL("update person set salary = ? where name = ?", new Object[]{13200, "关羽"});
}
//查
public void select(){
Cursor cursor = db.rawQuery("select * from person", null);
//把指针移动至下一行
while(cursor.moveToNext()){
//先通过列名,获取列索引,然后再获取该列的内容
String name = cursor.getString(cursor.getColumnIndex("name"));
String phone = cursor.getString(cursor.getColumnIndex("phone"));
int salary = cursor.getInt(cursor.getColumnIndex("salary"));
System.out.println(name + ";" + phone + ";" + salary);
}
}
}
事务
- 保证多条SQL语句要么同时成功,要么同时失败
- 最常见案例:银行转账
- 事务api
try {
//开启事务
db.beginTransaction();
...........
//设置事务执行成功
db.setTransactionSuccessful();
} finally{
//关闭事务
//如果此时已经设置事务执行成功,则sql语句生效,否则不生效
db.endTransaction();
}