Android存储基础

注意:本篇文章是本人阅读相关文章所写下的总结,方便以后查阅,所有内容非原创,侵权删。

文章内容来自于:
1.第一行代码 郭霖
2 Android SD卡存储

保存在内存中的数据是瞬时的,手机关机则消失。
而保存在存储设备中的数据是处于持久状态的。

目录

1.文件存储 /data/data//files/
2.SharedPreference存储 /data/data//shared_prefs/
3.数据库存储 /data/data/package_name/databases/
4.SD卡存储 /mnt/sdcard(/storage/emulated/0)
5.ContentProvider存储数据 (待补)
6.网络存储 (待补)

1.文件存储 /data/data//files/ (openFileOutput和openFileInput)

文件存储不对内容进行任何的格式化处理,所有数据原封不动地保存到文件中。
因此它比较适合存储一些简单的文本数据或二进制数据。

文件存储的核心技术:用Context提供的openFileOutput和openFileInput方法,然后利用java的各种流来进行读写操作。

1.1 将数据存储到文件中(存)

Context提供方法openFileOutput将数据存储到指定的文件中。
openFileOutput返回FileOutputStream,则可用java流的方式将数据写入到文件中。

//Context提供方法openFileOutput将数据存储到指定的文件中。
//参数一:文件名,不可包含路径,所有文件默认存储在/data/data//files/目录下
//参数二:文件的操作模式 有2种可选
//MODE_PRIVATE默认的操作模式,当指定同样文件名时,所写入的内容会覆盖原文件中的内容
//MODE_APPEND 如果文件已经存在,则往文件里追加内容,不存在则创建新文件。
//(废弃的2种)MODE_WORLD_READABLE和MODE_WORDLD_WRITEABLE表示允许其他程序对我们程序中的文件进行读写,但过于危险,已经废弃
public FileOutputStream openFileOutput(String name, int mode)

具体代码实现:

        String data = "hello my life";
        FileOutputStream fileOutputStream = openFileOutput("hello.txt", Context.MODE_PRIVATE);
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(fileOutputStream));
        bw.write(data);
        bw.close();

1.2 从文件中读取数据(取)

Context提供openFileInput()方法,用于从文件中读取数据。
返回FileInputStream,再通过java流的方式即可读取数据。

//只接受一个参数:即要读取的参数名
//则系统会自动到/data/data//files/目录下取加载这个文件,并返回一个FileInputStream对象
public FileInputStream openFileInput(String name)

具体代码实现:

        FileInputStream fileInputStream = openFileInput("hello.txt");
        BufferedReader br = new BufferedReader(new InputStreamReader(fileInputStream));
        StringBuilder sb = new StringBuilder();
        String line = null;
        while ((line = br.readLine()) != null) {
            sb.append(line);
        }
        Log.d("xl", sb.toString());
        br.close();

2.SharedPreference存储 /data/data//shared_prefs/

  • SharedPreference使用键值对的方式来存储数据。也就是当保存一条数据的时候,需要给这条数据提供一个对应的键,这样在读取数据的时候就可以通过这个键将相应的值取出来。
  • SharedPreference还支持多种不同的数据类型存储,如果存储的数据类型是整型,那么读取出来的数据也是整型。

SharedPreference存储的核心技术:得到SharedPreference对象,存得到SharedPreference的Editor进行put最后apply,取直接get

2.1将数据存到SharedPreference中(存)

首先要得到SharedPreferences对象,有3种方法:

//1.Context类中的getSharedPreferences方法
//参数一:用于指定sp文件的名称,如果指定的文件不存在,则创建一个,sp文件存放在/data/data//shared_prefs/目录下
//参数二:用于指定操作模式,目前只有MODE_PRIVATE可选,和传入0一样的效果。表示只有当前的应用程序才可以对这个SharedPreference文件进行读写,其他几种操作模式均已被废弃。
public SharedPreferences getSharedPreferences(String name, int mode)

//2.Activity的getPreferences()方法
//用法和getSharedPreferences相似
//只接受一个操作模式参数,因为使用这个方法会自动将当前活动的类名作为SharedPreference的文件名。
public SharedPreferences getPreferences(@Context.PreferencesMode int mode)

//3.PreferenceManager的getDefaultSharedPreferences方法
//静态方法,接受一个context参数,并自动使用当前应用程序的包名作为前缀来命名sp文件
public static SharedPreferences getDefaultSharedPreferences(Context context)

具体代码实现:

        //第一步:得到SharedPreferences对象
        SharedPreferences sharedPreferences = getSharedPreferences("data", MODE_PRIVATE);
        //第二步:得到SharedPreferences.Editor对象
        SharedPreferences.Editor editor = sharedPreferences.edit();
        //第三步:向SharedPreferences.Editor对象中添加数据
        editor.putString("name", "TOM");
        editor.putInt("age", 28);
        editor.putBoolean("married", false);
        //第四步:将添加的数据提交,从而完成数据存储的操作
        editor.apply();

2.2从SharedPreference中读取数据(取)

       //第一步:得到sharedPreferences对象
        SharedPreferences sharedPreferences = getSharedPreferences("data", MODE_PRIVATE);

        //第二步:取数据 
        //get方法 参数一:键 参数二:默认值(当传入的键找不到对应的值则返回默认值)
        String name = sharedPreferences.getString("name", "");
        int age = sharedPreferences.getInt("age", 0);
        boolean married = sharedPreferences.getBoolean("married", false);

        Log.d("xl", name + age + married);

3.数据库SQLite存储 /data/data/package_name/databases/

用于存储大量复杂的关系型数据。
比如:手机短信程序中可能会有多个会话,每个会话中又包含了很多条信息内容,且大部分会话还可能对应了电话簿中的某个联系人。

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

3.1 创建数据库

第一步:自定义类继承SQLiteOpenHelper

public class MySQLiteOpenHelper 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 MySQLiteOpenHelper(Context context, String name, SQLiteDatabase.CursorFactory factory, int version) {
        //Context context 上下文
        //String name 数据库名 创建数据库使用这里指定的名称
        //SQLiteDatabase.CursorFactory factory 允许我们在查询数据的时候返回一个自定义的cursor,一般传入null
        //int version 当前数据库的版本号,可用于对数据库进行升级操作。
        super(context, name, factory, version);
        mContext = context;
    }

    @Override
    public void onCreate(SQLiteDatabase db) {
        //重写onCreate,实现创建数据库的逻辑
        db.execSQL(CREATE_BOOK);
    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        //重写onUpgrade,实现升级数据库的逻辑
    }
}

第二步:创建数据库

        //构建出SQLiteOpenHelper实例
        MySQLiteOpenHelper dbHelper = new MySQLiteOpenHelper(this, "BookStore.db", null, 1);
        //创建或者打开一个现有的数据库(如果数据库已存在则直接打开(不会调用oncreate),否则创建一个新的数据库(调用oncreate))
        //可以调用它的getReadableDatabase()或者getWritableDatabase()方法
        //2个方法不同的是:当数据库不可写入的时候(如磁盘空间已满),getReadableDatabase()方法返回的对象将以只读的方式去打开数据库,而getWritableDatabase()方法则将出现异常。
        SQLiteDatabase database = dbHelper.getWritableDatabase();
      

3.2 升级数据库

例子:当项目中已经有一张Book表用于存放书的各种详细数据,如果想再添加一张Category表用于记录图书的分类。
第一步:重写SQLiteOpenHelper的onUpgrade方法

public class MySQLiteOpenHelper 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_CATEGORUY = "create table Category(id integer primary key autoincrement,category_name text,category_code integer)";


    private Context mContext;

    public MySQLiteOpenHelper(Context context, String name, SQLiteDatabase.CursorFactory factory, int version) {
        super(context, name, factory, version);
        mContext = context;
    }

    @Override
    public void onCreate(SQLiteDatabase db) {
        db.execSQL(CREATE_BOOK);
        db.execSQL(CREATE_CATEGORUY);
    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        //重写onUpgrade,实现升级数据库的逻辑
        //将原来的表先删除,否则无法执行oncreate方法
        db.execSQL("drop table if exists Book");
        db.execSQL("drop table if exists Category");
        onCreate(db);
    }
}

第二步:让onUpgrade执行

//修改SQLiteOpenHelper的第四个参数version
//传入比之前版本大的数,就可以让onUpgrade方法得到执行。
        MySQLiteOpenHelper dbHelper = new MySQLiteOpenHelper(this, "BookStore.db", null, 2);
        SQLiteDatabase database = dbHelper.getWritableDatabase();

3.3 数据库的CRUD

3.3.1 添加数据
        MySQLiteOpenHelper dbHelper = new MySQLiteOpenHelper(this, "BookStore.db", null, 2);
        SQLiteDatabase database = dbHelper.getWritableDatabase();
        ContentValues values = new ContentValues();
        //开始组装第一条数据
        values.put("name","A");
        values.put("author","A1");
        values.put("pages",222);
        values.put("price",19.95);
        database.insert("Book",null,values);
        //insert方法参数:
        //参数一:表名
        //参数二:在未指定添加数据的情况下给某些可为空的列赋值null
        values.clear();
        //开始组装第二条数据
        values.put("name","B");
        values.put("author","B1");
        values.put("pages",222);
        values.put("price",19.95);
        database.insert("Book",null,values);
3.3.2 更新数据
        MySQLiteOpenHelper dbHelper = new MySQLiteOpenHelper(this, "BookStore.db", null, 2);
        SQLiteDatabase database = dbHelper.getWritableDatabase();
        ContentValues values = new ContentValues();
        values.put("price",19.95);
        database.update("Book",values,"name=?",new String[]{"haha"});
        //第三、四个参数用来指定具体更新哪几行。
        //第三个参数对象SQL语句的where,表示更新所有name=?的行,?是一个占位符
        //第四个参数赋值一个字符串数组,为第三个参数中的每个占位符指定相应的内容。
3.3.3 删除数据
        MySQLiteOpenHelper dbHelper = new MySQLiteOpenHelper(this, "BookStore.db", null, 2);
        SQLiteDatabase database = dbHelper.getWritableDatabase();
        database.delete("Book", "page>?", new String[]{"500"});
3.3.4 查询数据
        MySQLiteOpenHelper dbHelper = new MySQLiteOpenHelper(this, "BookStore.db", null, 2);
        SQLiteDatabase database = dbHelper.getWritableDatabase();
        //query方法
        //参数一:查询表名 参数二:查询列名 参数三:where约束条件 参数四:为where约束条件中的占位符提供值 参数五:需要group by的列 参数六:对group by后进一步约束 参数七:指定查询结果的排序方式
        Cursor cursor = database.query("Book", null, null, null, null, null, null);
        if (cursor.moveToFirst()) {
            do {
                cursor.getString(cursor.getColumnIndex("name"));
                cursor.getString(cursor.getColumnIndex("author"));
                cursor.getInt(cursor.getColumnIndex("pages"));
                cursor.getDouble(cursor.getColumnIndex("price"));
            } while (cursor.moveToNext());
            cursor.close();
        }

4. SD卡存储 /mnt/sdcard(/storage/emulated/0)

SD卡存储空间比较大,当需要存取较大的文件时,可以使用SD卡存储。

SD卡存储的核心技术:对SD卡中文件的读和写所依据的原理为最常用的IO流操作,删除文件的方法采用File类的delete方法。

4.1 使用SD卡的注意点

1.权限问题
对SD卡进行读取工作时,需要声明权限,6.0之后需要动态申请权限。
如何动态申请权限查看Android权限(普通权限+危险权限)

//① SDCard中创建与删除文件权限

//② 从SDCard中读取文件的权限

//③ 向SDCard中写入文件的权限

2.SD卡状态
对SD卡进行操作之前应该首先判断SD卡的各种状态,便于之后的操作。

//使用Environment类中的方法getExternalStorageState()获得SD卡状态,若得到的值为MEDIA_MOUNTED,则代表目前SD卡“存在并且可以进行读写”。
if(Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState()))

3.SD卡路径

//使用以下方法可以获得SD卡存储路径,使用此路径会将文件存放到/mnt/sdcard文件夹中,但实际存放在/storage/emulated/0:
Environment.getExternalStorageDirectory();

4.2 SD卡的写文件

        if (Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())) {
            String fileName = "sdcontent.txt";
            String fileContent = "123456hahaha";

            File dir = Environment.getExternalStorageDirectory();
            File file = new File(dir, fileName);

            FileOutputStream fos = new FileOutputStream(file);
            fos.write(fileContent.getBytes());
            fos.close();

        } else {
            Toast.makeText(this, "SD卡不存在或状态异常,不能写入", Toast.LENGTH_SHORT).show();
        }

4.3 SD卡的读文件

        if (Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())) {

            String fileName = "sdcontent.txt";
            File dir = Environment.getExternalStorageDirectory();
            File file = new File(dir, fileName);

            FileInputStream fis = new FileInputStream(file);

            byte[] buffer = new byte[1024];
            int len = -1;
            StringBuilder sb = new StringBuilder();
            while ((len = fis.read(buffer)) != -1) {
                sb.append(new String(buffer, 0, len));
            }

            Log.d("xl", sb.toString());
            fis.close();
            
        } else {
            Toast.makeText(this, "SD卡不存在或状态异常,不能写入", Toast.LENGTH_SHORT).show();
        }

4.4 SD卡的删除文件

        if (Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())) {
            String fileName = "sdcontent.txt";
            File dir = Environment.getExternalStorageDirectory();
            File file = new File(dir, fileName);

            boolean delete = file.delete();
            if (delete) {
                Toast.makeText(this, "删除成功", Toast.LENGTH_SHORT).show();
            } else {
                Toast.makeText(this, "删除失败", Toast.LENGTH_SHORT).show();
            }

        } else {
            Toast.makeText(this, "SD卡不存在或状态异常,不能写入", Toast.LENGTH_SHORT).show();
        }

你可能感兴趣的:(Android存储基础)