安卓中的文件存储,SharePreference存储和数据库存储(详解持久化技术)

本文章参考郭霖老师第一行代码第二版的第六章,然后总结了一下并且加上自己的理解

1.文件存储
openFileOutput()方法,第一个参数是字符串或文件名(不包括路径,因为有默认路径),第二个参数为文件的操作模式,MODE_PRIVATE覆盖源文件,MODE_APPEND为往原文件里添加内容.
openFileOutput()方法返回的是一个FileOutputStream对象.

随便说一下java.IO层次体系结构:
主要的类如下:
1. File(文件特征与管理):用于文件或者目录的描述信息,例如生成新目录,修改文件名,删除文件,判断文件所在路径等。
2. InputStream(二进制格式操作):抽象类,基于字节的输入操作,是所有输入流的父类。定义了所有输入流都具有的共同特征。
3. OutputStream(二进制格式操作):抽象类,基于字节的输出操作,是所有输出流的父类。定义了所有输出流都具有的共同特征。
Java中字符是采用Unicode标准,一个字符是16位,即一个字符使用两个字节来表示。为此,JAVA中引入了处理字符的流。
4. Reader(文件格式操作):抽象类,基于字符的输入操作。
5. Writer(文件格式操作):抽象类,基于字符的输出操作.

还有一行这样代码来举例:

                 //缓冲流             字符流                 装饰字节流             字节流
bufferedReader = new BufferedReader(new InputStreamReader(new DataInputStream(socket.getInputStream())));

问题①
如果只用FileOutputStream fileOutputStream = new FileOutputStream("d:/text.txt");
不是也能输出到"d:/text.txt"吗?
为什么要用其它两个呢?能起到什么作用呢?
 
FileOutputStream 是字节流,它一个字节一个字节的向外边送数据
OutputStreamWrite是字符流,它一个字符一个字符的向外边送数据
它们有什么区别么?
解析:
      因为计算机是西方发明的,它们的英文字符占一个字节,而我们的中文是一个字符,占俩字节。如果用stream,你读出来的英语再倒也罢了,读出来的中文可就是乱码或者一个个“??"". 如果你用WRITER,就不会有乱码了

问题②
BufferedWriter  Buffer是一个缓冲区,为什么要用BUFFER呢?
    如果你直接用stream或者writer,你的硬盘可能就是一个字符或者一个字节    读写硬盘一次,可是你用了Buffer,你的硬盘就是读了一堆数据之后,读写一下硬盘。这样对你硬盘有好处。 

实例代码:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".MainActivity">

    <EditText
        android:id="@+id/account"
        android:hint="请输入你的账号"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />
    <Button
        android:id="@+id/to_second"
        android:text="to_second"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />

</LinearLayout>
package com.example.shareprefences;

import android.content.Context;
import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;

public class MainActivity extends AppCompatActivity {
    private EditText account;
    private Button to_second;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main_2);
        account = findViewById(R.id.account);
        to_second = findViewById(R.id.to_second);
        to_second.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent = new Intent(MainActivity.this,SecondActivity.class);
                startActivity(intent);
            }
        });
        try {
            String text  = load();
            account.setText(text);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        String InputText = account.getText().toString();
        try {
            save(InputText);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public  void save(String InputText) throws IOException {//把inputtext的存入到data中
        FileOutputStream outputStream = null;
        BufferedWriter bufferedWriter = null;
        outputStream = openFileOutput("data", Context.MODE_PRIVATE);
        bufferedWriter = new BufferedWriter(new OutputStreamWriter(outputStream));
        bufferedWriter.write(InputText);
        if(bufferedWriter != null){
            bufferedWriter.close();
        }
    }
    public String load() throws IOException {//把data中读取出来
        FileInputStream in = null;
        BufferedReader reader = null;
        StringBuilder content = new StringBuilder();
        in = openFileInput("data");
        reader = new BufferedReader(new InputStreamReader(in));
        String line = "";
        while((line = reader.readLine()) != null){
            content.append(line);
        }
        reader.close();
        return content.toString();
    }
}

解释:首先用openFileOutput方法转换成FileOutputStream对象outputStream,然后用OutputStreamWriter方法将outputStream转换为BufferedWriter对象,通过BufferedWriter将文本内容写入到文件中.

然后我们在AS菜单栏里View-Tool Windows-Device File Explorer-data-data-com.example.xxx(项目名)-files-data就可以看到我们输入的数据.

②从文件中读取数据


context类提供了openFileInput()方法,用于从文件中读取数据.这个方法要比openFileOutPut()简单,只接受一个参数,即要读取的文件名.并返回一个FileInputStream对象,然后再用java流的方式就可以将数据读取出来了.


解释:首先通过openFileInput()方法获取到了FileInputStream对象in,然后再用InputStreamReader()方法将in转换成BufferedReader对象,这样就可以整行地读取数据了,最后返回content.toString().

2.SharePreferences存储

使用键值对的方式来存储,也就是一个value对应一个key,在读取数据时通过这个key来把这个value取出来,而且SharePreferences支持多种不同的数据类型存储.
要想使用SharePreferences来存储数据,首先获取到SharePreferences对象.
PreferenceManager类中的getDefaultPreference方法
静态方法,只接受一个context参数,
第一步:调用SharePreferences对象的edit方法来获取一个SharePreferences.Editor对象
第二步:向SharePreferences.Editor对象添加数据,如putString().
第三步:调用apply方法,将数据提交,从而进行数据存储操作.

举栗代码:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".SecondActivity">
    <EditText
        android:id="@+id/data_1"
        android:hint="请输入你的密码"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />
    <Button
        android:id="@+id/save"
        android:text="SAVE_DATA"
        android:layout_marginEnd="35dp"
        android:layout_marginStart="35dp"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginLeft="35dp" />
    <Button
        android:id="@+id/read"
        android:text="READ_DATA"
        android:layout_marginEnd="35dp"
        android:layout_marginStart="35dp"
        android:layout_marginLeft="35dp"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />
    <EditText
        android:id="@+id/data_2"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />
    <Button
        android:id="@+id/to_the_third"
        android:text="TO THE THIRD"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />
</LinearLayout>
package com.example.shareprefences;

import android.content.Intent;
import android.content.SharedPreferences;
import android.preference.PreferenceManager;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.EditText;

import java.util.prefs.PreferenceChangeEvent;

public class SecondActivity extends AppCompatActivity {
    private EditText data_1;
    private Button save;
    private Button read;
    private EditText data_2;
    private Button to_third;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_second);
        data_1 = findViewById(R.id.data_1);
        data_2 = findViewById(R.id.data_2);
        save = findViewById(R.id.save);
        read = findViewById(R.id.read);
        to_third = findViewById(R.id.to_the_third);
        save.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                        SharedPreferences.Editor editor =
                                getSharedPreferences("data", MODE_PRIVATE).edit();
                        editor.putString("password", String.valueOf(data_1.getText()));
                        editor.apply();

            }
        });
        read.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                SharedPreferences preferences = getSharedPreferences("data",MODE_PRIVATE);
                String password = preferences.getString("password","");
                data_2.setText(password);
            }
        });
        to_third.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent = new Intent(SecondActivity.this,third.class);
                startActivity(intent);
            }
        });
    }
}

这里我们把第一个EditText中的数据保存下来,在第二个中读取出来,这里的password就是键,第一个EditText的值就是password键对应的值,所以在第二个里就可以通过password找到相应的值.

然后我们在菜单栏里View-Tool Windows-Device File Explorer-data-data-com.example.xxx(项目名)-share_prefs-data就可以看到我们输入的数据,如果没有点击上边的模拟器刷新一下.

3.数据库存储

推荐一下我另外一篇博客,我感觉是对Litepal数据库的最好的实践

学生管理系统APP

先说一些基本常用的语句:

打开数据库:

LitePal.getDatabase();

增:

student.save();
students.add(student);

删:

DataSupport.deleteAll(Saved_Student.class,"account=?",student.getStudent_number());

查:

List<Student> list = DataSupport.where("student_number = ?", ID).find(Student.class);
if (list.size() != 0) {
            student = list.get(0);
            Log.e("ID:==",student.getStudent_number()+"--------");
        }

改:

student.setID_password(MD5HTTL.md5(mess1));
student.updateAll("ID_password=?",MD5HTTL.md5(mess1));

然后再说一些概念
首先我们找到我们SDK文件夹中的adb,C:\Users\dell\AppData\Local\Android\Sdk\platform-tools(你们电脑中的adb地址,我这里只是举了我自己电脑adb的地址)

然后在电脑的属性-高级系统设置-环境变量-系统变量中的Path将上面的地址复制粘贴过去

如图:


我们这里要用litepal数据库,添加依赖:

api 'org.litepal.android:core:1.4.1'

在manifests中添加:

android:name="org.litepal.LitePalApplication"

创建Book类并继承DataSupport(支持增删查改操作):

public class Book extends DataSupport {
    String bookname;
    int bookprice;
    String author;

    public String getBookname() {
        return bookname;
    }

    public void setBookname(String bookname) {
        this.bookname = bookname;
    }

    public int getBookprice() {
        return bookprice;
    }

    public void setBookprice(int bookprice) {
        this.bookprice = bookprice;
    }

    public String getAuthor() {
        return author;
    }

    public void setAuthor(String author) {
        this.author = author;
    }

然后在Project模式下src-main下新建一个叫assets的directory,然后在里面创建一个New Resource File叫做litepal.xml(Resource type就默认就可以),然后把这个文件移到assets包里面.

<?xml version="1.0" encoding="utf-8"?>
<litepal>
    <dbname value = "BookStore">

    </dbname>
    <version value="1"></version>
    <list>
        <mapping class="com.example.shareprefences.Book"></mapping>
    </list>
</litepal>

如果要再添加一个表的话,就在原来的litepal.xml中(value+1,并加上<mapping>):

<?xml version="1.0" encoding="utf-8"?>
<litepal>
    <dbname value = "BookStore">

    </dbname>
    <version value="2"></version>
    <list>
        <mapping class="com.example.shareprefences.Book"></mapping>
        <mapping class="com.example.shareprefences.Press"></mapping>
    </list>
</litepal>

举栗代码

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".third">
    <Button
    android:id="@+id/save_data"
    android:text="save_data"
    android:layout_marginEnd="45dp"
    android:layout_marginStart="45dp"
    android:layout_width="match_parent"
    android:layout_height="wrap_content" />
    <EditText
        android:id="@+id/bookname"
        android:hint="请输入你想卖的书"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />
    <EditText
        android:id="@+id/bookprice"
        android:hint="请输入你想卖多少钱"
        android:inputType="number|numberDecimal"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />
    <EditText
        android:id="@+id/author"
        android:hint="请输入书的作者"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />
    <Button
        android:id="@+id/upload"
        android:text="添加"
        android:textSize="18sp"
        android:layout_marginEnd="45dp"
        android:layout_marginStart="45dp"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />
    <Button
        android:id="@+id/delete"
        android:text="删除"
        android:textSize="18sp"
        android:layout_marginEnd="45dp"
        android:layout_marginStart="45dp"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />
    <Button
        android:id="@+id/update"
        android:text="更新"
        android:textSize="18sp"
        android:layout_marginEnd="45dp"
        android:layout_marginStart="45dp"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />
</LinearLayout>

界面就这样:(只是举个例子界面不要在意,实现功能就好)

:

public class third extends AppCompatActivity {
    private Button save_data;
    private EditText bookname;
    private EditText bookprice;
    private EditText bookauthor;
    private Button upload;
    private Button delete;
    private Button update;
    Book book = new Book();
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_third);
        save_data  = findViewById(R.id.save_data);
        bookname = findViewById(R.id.bookname);
        bookauthor = findViewById(R.id.author);
        bookprice = findViewById(R.id.bookprice);
        upload = findViewById(R.id.upload);
        delete = findViewById(R.id.delete);
        update = findViewById(R.id.update);
        save_data.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                LitePal.getDatabase();
            }
        });
        upload.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                book.setBookname(bookname.getText().toString());
                book.setAuthor(bookauthor.getText().toString());
                book.setBookprice(bookprice.getText().toString());
                book.save();
            }
        });
        delete.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                DataSupport.deleteAll(Book.class);
            }
        });
        update.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                book.updateAll();
            }
        });

    }
}

用cmd查看数据库信息:(我这里的模拟器用的AS自带的模拟器安卓版本为6.0,系统为7.0的模拟器好像用不了,如果是手机的话要root)

通过命令行就可以看到我们创建的表,这里我创建了一个book,一个press表

一开始查询:

添加一条信息点击添加:

添加之后我们再查一遍:


看到了我们有了一条新加的消息.

然后我们点击删除,删除之后再查就什么都没有了

发布了69 篇原创文章 · 获赞 50 · 访问量 5万+

猜你喜欢

转载自blog.csdn.net/qq873044564/article/details/89435424