【移动安全技术】_第五战_安卓数据读写



任务内容

  通过文件操作和数据库操作进行数据读写。

1、完成安卓对文件的读写操作。分成读写不一致和一致两种情况。
2、完成安卓对SQLite数据库的操作。包括数据库建立、创建表格、插入数据、更新数据、删除数据以及查询数据。

附加题:对SQLite的所有操作都是根据用户的输入完成。

评分:完成1和2的功能起评分为80分,附加题15分。其他分数的增减根据报告给出。

  概述:Android系统主要提供3种方式实现数据持久化功能:文件存储、SharedPreference存储、数据库存储。



文件存储

  文件存储是Android最基本的数据存储方式,不对存储的内容进行任何格式化处理。

  context类提供FileOutputStream openFileOutput(filename, mode)方法,将数据存储到指定的文件中。该方法返回文件输出流对象,通过该对象就能用Java流将数据写入文件。

  指定的文件名不能包含路径,默认存储到/data/data/<packagename>/files/目录下。
  操作模式主要有两种,默认模式mode_private会重写文件,mode_append用于追加文件内容。

  写入文件的执行过程:
  openFileOutput(filename, mode) ,返回文件输出流对象FileOutputStream -->输出流写入对象OutputStreamWriter() --> 缓冲区写入对象BufferedWriter(),关闭缓冲区写入对象.close()
  读取文件的执行过程:
  openFileInput(filename) ,返回文件输入流对象FileOutputStream --> 输入流写入对象InputStreamReader() --> 缓冲区读取对象BufferedReader() --> 把数据存放到StringBuilder对象,关闭缓冲区读取对象。

	将数据写入文件的自定义方法:
public void save() {
        String data = "saved data";
        FileOutputStream out = null;
        BufferedWriter writer = null;
        try{
            out = openFileOutput("datafile",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();
            }
        }
    }

	从文件中读取数据的自定义方法:
public String load() {
        FileInputStream in = null;
        BufferedReader reader = null;
        StringBuilder content = new StringBuilder();
        try {
            in = openFileInput("datafile");
            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();
    }

  接下来运行一个简单实现读写功能的安卓程序:
在EditText输入数据,将数据保存到文件,退出程序;
重新打开程序,读取文件中的数据,打印到EditText框内。

	仓库文件添加布局和EditText输入框:
<LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="horizontal">

        <EditText
            android:id="@+id/edit"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:ems="10"
            android:inputType="textPersonName"
            android:hint="input your data" />
    </LinearLayout>

	MainActivity.java文件完整的包和代码:
package com.example.fifth_writeread;

import androidx.appcompat.app.AppCompatActivity;

import android.content.Context;
import android.os.Bundle;
import android.text.TextUtils;
import android.widget.EditText;
import android.widget.Toast;

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

public class MainActivity extends AppCompatActivity {

    private EditText edit ;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        edit = (EditText) findViewById(R.id.edit);

        String inputText = load();
        if( !TextUtils.isEmpty(inputText)){ // 非空
            edit.setText(inputText);
            edit.setSelection(inputText.length());
            Toast.makeText(this,"Restoring succeeded", Toast.LENGTH_SHORT).show();
        }

    }

    protected void onDestroy() {
        super.onDestroy();
        String inputText = edit.getText().toString();   // 获取EditText的输入数据
        save(inputText);    // 调用函数保存数据到文件
    }


    public void save(String inputText) {

        FileOutputStream out = null;
        BufferedWriter writer = null;
        try{
            out = openFileOutput("datafile",MODE_PRIVATE);	// 文件输出流
            writer = new BufferedWriter(new OutputStreamWriter(out));	// 输出流写入。缓冲区写入。
            writer.write(inputText);
        } catch(IOException e){	// 捕获异常
            e.printStackTrace();
        } finally {
            try{	// 关闭文件
                if(writer != null){
                    writer.close();
                }
            } catch(IOException e){	// 捕获异常
                e.printStackTrace();
            }
        }
    }


    public String load() {
        FileInputStream in = null;
        BufferedReader reader = null;
        StringBuilder content = new StringBuilder();
        try {
            in = openFileInput("datafile");
            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();
    }

}

  执行效果:打开程序输入数据。

在这里插入图片描述
  执行效果:重新打开程序,成功打印刚才输入的临时数据:

在这里插入图片描述


SQLite数据库存储

概述

  Android系统内置了数据库!SQLite是轻量级的关系型数据库,通常只需要几百KB的内存,因此特别适合在移动设备上使用。

  Android专门提供SQLiteOpenHelper帮助类,可以简单地实现数据库的创建和升级。
SQLiteOpenHelper是一个抽象类,使用前提是创建自己的帮助类去继承他。

函数方法说明
抽象方法onCreate()必须在自定义帮助类里重写这两个方法,
抽象方法onUpgrade()然后分别在两个方法中实现创建、升级数据库的逻辑
getReadableDatabase()这两个方法都可以创建/打开数据库,返回可对数据库进行读写操作的对象
getWritableDatabase()区别在于,当数据库不可写入(比如磁盘已满),getReadableDatabase()返回的对象会以只读方式打开数据库,而getWritableDatabase()方法会出现异常。


建立数据库和表

  创建数据库BookStore.db,新建一张Book表,表中有id(主键)、作者、书名等列:

	1.建表关键代码:(合并1和2的代码,在布局中添加id为create的按钮,即为运行代码)
public class MyDatabaseHelper extends SQLiteOpenHelper {
        public static final String CREATE_BOOK = "create table Book ( "
                +"id integer primary key autoincrement,"	// 自增长autoincrement
                +"author text,"
                +"name text)" ;
            // 静态变量-建表语句
        private Context MyContext ;	// 私有类Context实例

        // 类的构造方法
        public MyDatabaseHelper(Context context, String name, SQLiteDatabase.CursorFactory factory, int version) {
            super(context, name, factory, version) ;
            MyContext = context ;	// 传入Context实例
        }

        @Override
        public void onCreate( SQLiteDatabase db) {
            db.execSQL(CREATE_BOOK) ;	// 建立数据库、建表,执行之后打印提示
            Toast.makeText( MyContext , "Create succeeded", Toast.LENGTH_SHORT).show();	// 建表提示信息
        }

        @Override
        public void onUpgrade( SQLiteDatabase db, int oldVersion , int newVersion) {
        }
    }

}

	2.MainActivity.java文件的其他代码:
package com.example.fifth_sqlite;

import androidx.appcompat.app.AppCompatActivity;

import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;
public class MainActivity extends AppCompatActivity {

    private MyDatabaseHelper dbHelper;	// 自定义数据库的实例
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

		 //  自定义数据库实例:传入四个参数,第二个是数据库名,第四个是版本号。
		 // 此时会进行建库建表操作
        dbHelper = new MyDatabaseHelper(this, "BookStore.db", null, 1);	
       

        Button createDatabase = (Button) findViewById(R.id.create);
        createDatabase.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                dbHelper.getWritableDatabase();	// 点击按钮,调用数据库实例的写入函数,创建数据库
            }
        });
    }

  执行效果:
在这里插入图片描述


升级数据
	2.新建第二个表users
	在自定义数据库类中添加建表语句,定义为私有静态变量
public static final String CREATE_USERS = "create table users( "
	+ "id integer primary key autoincrement,"
	+ "username text, "
	+ "password text)";
	在onUpgrade()中添加
 @Override
        public void onUpgrade( SQLiteDatabase db, int oldVersion , int newVersion) {
        db.execSQL("drop table if exist Book");
        db.execSQL("drop table if exist Category");
        onCreate(db);	// 表存在就删除,避免报错。调用创建函数,新建两张表。
        }
	创建自定义数据库实例时,需要传入更大的版本号来更新数据库,注意是整数类型
	dbHelper = new MyDatabaseHelper(this, "BookStore.db" , null , 2)	


添加数据-增删改查CRUD
	1.添加数据:创建添加数据的按钮,监听点击操作
public void  onClick( View v) {
	SQLiteDatabase db = dbHelper.getWritableDatabase();
	ContentValues values = new ContentValues();
	// 组装第一条数据
	values.put("id" , 0) ;
	values.put("author", "dashi");
	values.put("name", "how to be a dashi");
	db.insert("Book", null, values); 	// 插入第一条数据
}

	2.更新数据:创建更新数据的按钮,监听点击操作
public void  onClick( View v) {
	SQLiteDatabase db = dbHelper.getWritableDatabase();
	ContentValues values = new ContentValues();
	values.put("name", "how to be a dashi 2");
	db.update("Book", values, "name= ?" , new String[] { "how to be a dashi" } );
}

	3.删除数据:创建删除数据的按钮,监听点击操作
public void  onClick( View v) {
	SQLiteDatabase db = dbHelper.getWritableDatabase();
	db.delete("Book", "id = ?", new String[] { "0" } );
}

	4.查询数据:创建查询数据的按钮,监听点击操作
public void  onClick( View v) {
	SQLiteDatabase db = dbHelper.getWritableDatabase();
	// 查询Book表中所有的数据
	Cursor cursor = db.query("Book", null, null, null, null, null, null);
	if( cursor.moveToFirst()) {
		do {
			// 遍历Cursor对象,取出数据并打印
			int id = cursor.getInt(cursor.getColumnIndex("id"));
			String author = cursor.getString(cursor.getColumnIndex("author"));
			String name = cursor.getString(cursor.getColumnIndex("name"));
			Log.d("MainActivity", "book id is " + id);
			Log.d("MainActivity", "book author is " + author);
			Log.d("MainActivity", "book name is " + name);
		} while( cursor.moveToNext());
	}
}


全部代码

  完整的代码:

	1. MainActivity.main代码
package com.example.fifth_sqlite;

import androidx.appcompat.app.AppCompatActivity;

import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;

public class MainActivity extends AppCompatActivity {

    private MyDatabaseHelper dbHelper;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        dbHelper = new MyDatabaseHelper(this, "BookStore.db", null, 1);

        Button createDatabase = (Button) findViewById(R.id.create);
        createDatabase.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                dbHelper.getWritableDatabase();
            }
        });

        Button add = (Button) findViewById(R.id.add);
        add.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                SQLiteDatabase db = dbHelper.getWritableDatabase();
                ContentValues values = new ContentValues();
                // 组装第一条数据
                values.put("id" , 0) ;
                values.put("author", "dashi");
                values.put("name", "how to be a dashi");
                db.insert("Book", null, values); 	// 插入第一条数据

            }
        });

        Button delete = (Button) findViewById(R.id.delete);
        delete.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                SQLiteDatabase db = dbHelper.getWritableDatabase();
                db.delete("Book", "id = ?", new String[] { "0" } );

            }
        });

        // 由于更新数据,需要传入更大的数据库版本号,需要设置dbHelper = new MyDatabaseHelper(this, "BookStore.db", null, 1+n);
        // 如果不传入更大的版本号,更新就会产生错误,所以此处不执行代码
        Button update = (Button) findViewById(R.id.update);
        update.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
//                SQLiteDatabase db = dbHelper.getWritableDatabase();
//                ContentValues values = new ContentValues();
//                values.put("name", "how to be a dashi 2");
//                db.update("Book", values, "name= ?" , new String[] { "how to be a dashi" } );
            }
        });

        Button retrieve = (Button) findViewById(R.id.retrieve);
        retrieve.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                SQLiteDatabase db = dbHelper.getWritableDatabase();
                // 查询Book表中所有的数据
                Cursor cursor = db.query("Book", null, null, null, null, null, null);
                if(cursor.moveToFirst()) {
                    do {
                        // 遍历Cursor对象,取出数据并打印
                        int id = cursor.getInt(cursor.getColumnIndex("id"));
                        String author = cursor.getString(cursor.getColumnIndex("author"));
                        String name = cursor.getString(cursor.getColumnIndex("name"));
                        Log.d("MainActivity", "book id is " + id);
                        Log.d("MainActivity", "book author is " + author);
                        Log.d("MainActivity", "book name is " + name);
                    } while( cursor.moveToNext());
                }
            }
        });

    }

    public class MyDatabaseHelper extends SQLiteOpenHelper {
        public static final String CREATE_BOOK = "create table Book ( "
                +"id integer primary key autoincrement,"	// 自增长autoincrement
                +"author text,"
                +"name text)" ;
            // 静态变量-建表语句
        private Context MyContext ;	// 私有类Context实例

        // 类的构造方法
        public MyDatabaseHelper(Context context, String name, SQLiteDatabase.CursorFactory factory, int version) {
            super(context, name, factory, version) ;
            MyContext = context ;	// 传入Context实例
        }

        @Override
        public void onCreate( SQLiteDatabase db) {
            db.execSQL(CREATE_BOOK) ;	// 建表
            Toast.makeText( MyContext , "Create succeeded", Toast.LENGTH_SHORT).show();	// 建表提示信息
        }

        @Override
        public void onUpgrade( SQLiteDatabase db, int oldVersion , int newVersion) {
        }
    }

}

	2. activity_main.xml的按钮代码:
<LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">

        <Button
            android:id="@+id/create"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="创建数据库" />

        <Button
            android:id="@+id/add"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="添加数据" />

        <Button
            android:id="@+id/delete"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="删除数据" />

        <Button
            android:id="@+id/update"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="更新数据" />

        <Button
            android:id="@+id/retrieve"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="查询数据" />
    </LinearLayout>


执行效果

  主页面:

在这里插入图片描述

  1.添加数据:点击添加数据按钮,然后点击查询数据按钮。

在这里插入图片描述

  2.删除数据:点击删除数据按钮,然后点击查询数据按钮,返回数据为空。
在这里插入图片描述

  3.更新数据:修改自定义数据库实例的版本号为2,重新打开安卓程序。点击更新数据按钮,然后点击查询数据按钮,成功把书名“how to be a dashi”修改为“how to be a dashi 2”

在这里插入图片描述


参考

  《第一行代码 Android 第2版》——郭霖著

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值