android public 简书,Android 文件存储

1.IO文件读取

IO流类图

40c541592aa6

IO流

分类

按照读取数据类型不同分为字节流和字符流

按照数据流向不同分为输入流和```输出流

常用方式

字节流FileInputStream 和 FileOutputStream文件读写

//写入文件

private void writeFile() {

FileOutputStream outputStream = null;

try {

outputStream = new FileOutputStream(path);

String str = "asdasdadadad";

outputStream.write(str.getBytes());

outputStream.close();

}

...注意异常处理

}

//读取文件

FileInputStream inputStream = null;

try {

inputStream = new FileInputStream(file);

StringBuilder builder = new StringBuilder();

int i = 0;

while ((i = inputStream.read() )!= -1){

builder.append((char)i);

}

//文件信息

builder.toString();

inputStream.close();

}..异常处理

BufferedOutputStream与BufferedInputStream

BufferedInputStream是带缓冲区的输入流,默认缓冲区大小是8M,能够减少访问磁盘的次数,提高文件读取性能;BufferedOutputStream是带缓冲区的输出流,能够提高文件的写入效率。BufferedInputStream与BufferedOutputStream分别是FilterInputStream类和FilterOutputStream类的子类,实现了装饰设计模式。

FileOutputStream outputStream = null;

BufferedOutputStream bufferedOutputStream;

try {

outputStream = new FileOutputStream(path);

bufferedOutputStream = new BufferedOutputStream(outputStream);

String str = "sssssssasdafafasda";

bufferedOutputStream.write(str.getBytes());

//写完毕后要将数据刷新到文件中

bufferedOutputStream.flush();

outputStream.close();

bufferedOutputStream.close();

} //异常处理

FileInputStream inputStream = null;

BufferedInputStream bufferedInputStream;

try {

inputStream = new FileInputStream(file);

bufferedInputStream = new BufferedInputStream(inputStream);

StringBuilder builder = new StringBuilder();

//缓冲区 不设置默认为8K

byte[] bytes = new byte[1024];

int i = 0;

while ((i = bufferedInputStream.read(bytes) )!= -1){

builder.append(new String(bytes));

}

builder.toString()

inputStream.close();

}//异常处理

字符流操作文件

FileWriter与FileReader读写文件

//写文件

private void writerFile() {

FileWriter writer = null;

try {

writer = new FileWriter(path);

String str = "中文测试呢";

writer.write(str);

writer.close();

} //异常处理

}

//读文件

private void readerFile() {

FileReader reader = null;

try {

reader = new FileReader(file);

StringBuilder builder = new StringBuilder();

int i = 0;

while ((i = reader.read() )!= -1){

builder.append((char)i);

}

mResult.setText(builder.toString());

reader.close();

} //异常处理

}

BufferedReader和BufferedWriter,带缓冲区的字符流。

private void bufferReaderFile() {

BufferedReader reader = null;

try {

reader = new BufferedReader(new FileReader(file));

StringBuilder builder = new StringBuilder();

String str = "";

while ((str = reader.readLine()) != null){

builder.append(str);

}

mResult.setText(builder.toString());

reader.close();

} //异常处理

}

private void bufferWriterFile() {

BufferedWriter writer = null;

try {

writer = new BufferedWriter(new FileWriter(path));

String str = "BufferedWriter测试呢";

writer.write(str);

writer.close();

} //异常处理

}

InputStreamReader将字节流转换为字符流

InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "GB2312");

ObjectOutputStream与ObjectInputStream序列化与反序列化

//序列化

private void writeObject(){

ObjectOutputStream objectOutputStream = null;

try {

objectOutputStream = new ObjectOutputStream(new FileOutputStream(path));

Student student = new Student();

objectOutputStream.writeObject(student);

objectOutputStream.close();

} catch (IOException e) {

e.printStackTrace();

}finally {

if (null != objectOutputStream){

try {

objectOutputStream.close();

} catch (IOException e) {

e.printStackTrace();

}

}

}

}

//反序列化

private void readObject(){

ObjectInputStream objectInputStream = null;

try {

objectInputStream = new ObjectInputStream(new FileInputStream(path));

Student student = (Student) objectInputStream.readObject();

mResult.setText(student.toString());

objectInputStream.close();

} catch (IOException e) {

e.printStackTrace();

} catch (ClassNotFoundException e) {

e.printStackTrace();

} finally {

if (null != objectInputStream){

try {

objectInputStream.close();

} catch (IOException e) {

e.printStackTrace();

}

}

}

}

1.序列化 ID 问题

虚拟机是否允许反序列化,不仅取决于类路径和功能代码是否一致,一个非常重要的一点是两个类的序列化 ID 是否一致(就是 private static final long serialVersionUID = 1L)。

2.静态变量序列化

序列化保存的是对象的状态,静态变量属于类的状态,因此 序列化并不保存静态变量。

3.父类的序列化与 Transient 关键字

一个子类实现了 Serializable 接口,它的父类都没有实现 Serializable 接口,序列化该子类对象,然后反序列化后输出父类定义的某变量的数值,该变量数值与序列化时的数值不同。

解决方法:要想将父类对象也序列化,就需要让父类也实现Serializable 接口。或者有默认的无参的构造函数,在构造函数中完成初始化。

Transient 关键字的作用是控制变量的序列化,在变量声明前加上该关键字,可以阻止该变量被序列化到文件中,在被反序列化后,transient 变量的值被设为初始值,如 int 型的是 0,对象型的是 null。

4.自定义序列化过程

虚拟机会试图调用对象类里的 writeObject 和 readObject 方法,进行用户自定义的序列化和反序列化,如果没有这样的方法,则默认调用是 ObjectOutputStream 的 defaultWriteObject 方法以及 ObjectInputStream 的 defaultReadObject 方法。用户自定义的 writeObject 和 readObject 方法可以允许用户控制序列化的过程。

//序列化过程

private void writeObject(ObjectOutputStream out) {

try {

ObjectOutputStream.PutField putFields = out.putFields();

career = "new Student";//模拟加密

putFields.put("career", career);

out.writeFields();

} catch (IOException e) {

e.printStackTrace();

}

}

//反序列化过程

private void readObject(ObjectInputStream in){

try {

ObjectInputStream.GetField getField = in.readFields();

career = (String) getField.get("career", "");

} catch (ClassNotFoundException e) {

e.printStackTrace();

} catch (IOException e) {

e.printStackTrace();

}

}

5.序列化存储规则

Java 序列化机制为了节省磁盘空间,具有特定的存储规则,当写入文件的为同一对象时,并不会再将对象的内容进行存储,而只是再次存储一份引用,新增一些控制信息。反序列化时,恢复引用关系该存储规则极大的节省了存储空间。

2.sqlite数据库

sqlite数据库的使用:

1、继承SQLiteOpenHelper

public class DbHelper extends SQLiteOpenHelper {

//数据库名称

private final static String dbName = "test.db";

//表名称

public final static String dbTable = "testTable";

public DbHelper(Context context){

this(context,dbName,null,1);

}

public DbHelper(Context context, String name, SQLiteDatabase.CursorFactory factory, int version) {

//上下文,数据库名称,游标工厂,版本号

super(context, name, factory, version);

}

@Override

public void onCreate(SQLiteDatabase sqLiteDatabase) {

//创建表操作

String sql = "create table if not exists "+ dbTable+"(Id integer /*primary key*/ , Name text ,

Price integer , Age integer)";

sqLiteDatabase.execSQL(sql);

}

@Override

public void onUpgrade(SQLiteDatabase sqLiteDatabase, int oldVersion, int newVersion) {

//更新操作一般有如下步骤,本次演示只默认删除重建

if (oldVersion != newVersion) {

//1.创建临时表保存数据

//2.删除现有表

//3.创建新表

//4.复制临时表数据至新表

//5.删除临时表

sqLiteDatabase.execSQL("DROP TABLE IF EXISTS " + dbTable);

onCreate(sqLiteDatabase);

}

}

}

2、创建数据库操作类,持有SQLiteOpenHelper子类对象,操作数据增删改查:

//插入

public void insert(){

SQLiteDatabase writableDatabase = mDbHelper.getWritableDatabase();

writableDatabase.beginTransaction();

writableDatabase.execSQL("insert into " + mDbHelper.dbTable+"(Id,Name,Price,Age)values (1,'xj2',12,18)");

writableDatabase.execSQL("insert into " + mDbHelper.dbTable+"(Id,Name,Price,Age)values (2,'xj3',13,18)");

writableDatabase.execSQL("insert into " + mDbHelper.dbTable+"(Id,Name,Price,Age)values (3,'xj4',14,18)");

writableDatabase.execSQL("insert into " + mDbHelper.dbTable+"(Id,Name,Price,Age)values (4,'xj5',15,18)");

writableDatabase.execSQL("insert into " + mDbHelper.dbTable+"(Id,Name,Price,Age)values (5,'xj6',16,18)");

writableDatabase.execSQL("insert into " + mDbHelper.dbTable+"(Id,Name,Price,Age)values (6,'xj7',17,18)");

writableDatabase.setTransactionSuccessful();

writableDatabase.endTransaction();

}

//查询

public String query(){

SQLiteDatabase writableDatabase = mDbHelper.getWritableDatabase();

Cursor query = writableDatabase.query(mDbHelper.dbTable, null, null, null, null, null, null);

StringBuilder builder = new StringBuilder();

while (query.moveToNext()){

//查询数据

int id = query.getInt(query.getColumnIndex("Id"));

}

return builder.toString();

}

其余方法等同.数据库详细语法后续再详细学习。

数据库操作有两种方式,一种如insert方法一样执行SQL语句,另一种如query方法一样使用SQLiteDatabase 封装过的方法。

sqlite是线程安全的吗

Android中SQLiteDatabase为sqlite提供了线程安全的保证,因此Android中sqlite数据库是线程安全的。

sqlite是线程安全的吗

数据库保存在/data/data/pageName/databases/dbName.db,其中pageName为包名,dbName为数据库名称。

3.SharedPreferences

SharedPreferences是Android轻量级的存储方式,使用方式如下

public void saveSp(){

SharedPreferences preferences = getSharedPreferences("perfer_file",MODE_PRIVATE);

SharedPreferences.Editor edit = preferences.edit();

edit.putString("key",value);

edit.putInt("key",value);

....

edit.apply();/edit.commit();

}

public void readSp(){

SharedPreferences preferences = getSharedPreferences("xujie,",MODE_PRIVATE);

String value= preferences.getString("key", defaultValue);

int value= preferences.getInt("key", defaultValue);

...

}

存取使用SharedPreferences.Editor来完成。数据存储在/data/data/pageName/shared_prefs/perfer_file.xml里面,结构如下:

value

注意点:

1.SharedPreferences对大小没有限制,但是如果存储数据过大会导致性能问题,因此要存储合理的数据。

2.SharedPreferences只能存储基本类型的数据。

3.SharedPreferences线程不安全。

4.ContentProvider

四大组件之一,数据通过ContentProvider存储在别的工程中。可参考四大组件文章。

5.网络存储

数据存储在网络上,通过Http等协议获取数据,常用库为Okhttp等。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值