AndroidStudio中利用openFileOutput将数据保存在文件中,利用openFileInput读取文件中的数据

本文介绍了一种在Android应用中实现数据持久化的方法,通过在Activity的生命周期中使用onDestroy()函数来保存输入框的数据,并在下次启动时读取这些数据。文章详细解释了如何使用Context类的openFileOutput()和openFileInput()方法,以及如何利用缓冲字符流提高读写速度。
一、要实现的功能

将输入框中的数据保存到指定文件名的文件中,实现数据的持久化;如果数据已经保存了,活动下次再启动的时候,就将保存在文件中的数据读取出来,显示在输入框中。

二、基本知识
  1. 利用活动生命周期中的一个回调函数onDestroy(),在活动被销毁之前,将数据写入到文件当中。例如按下返回键的时候,活动就被销毁,这个方法里面的代码就会被执行。
  2. 利用TextUtils中的isEmpty(CharSequence str)方法可以轻松地判断一个字符串变量是不是null,以及这个字符串是不是空字符串(字符串长度为0)。java中传统的方式是这么写的:
    if(string!=null&&string.length()!=0)
    ,这种方式比较麻烦,用TextUtils的话就比较方便了。
  3. ① 利用Contex类中的openFileOutput(String name, int mode)方法可以获取一个FileOutputStream对象,这个方法第一个参数传入的是文件名,第二个参数是文件的操作模式,取值主要有MODE_PRIVATE、 MODE_APPEND,如果文件已经存在了,第一种方式会把文件中原来的内容覆盖掉,第二种方式则是在原来的基础上进行追加数据。
    ②利用Contex类中的openFileInput(String name)可以获取一个FileInputStream对象,方法中传入的参数是文件的名称。
    除此之外,文件的读写操作就没有什么特殊的了,用到的都是JDK中的IO知识,这里还用到了缓冲字符流,主要是为了提高读取、写入的速度。
三、代码
  1. java代码:
import android.support.v7.app.AppCompatActivity;
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 et;

    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        et=findViewById(R.id.et);
        String load = load();
        if (!TextUtils.isEmpty(load))//如果文件存在
        {
            et.setText(load);
            et.setSelection(load.length());//将光标移动到输入框的末尾
            Toast.makeText(this,"从文件中恢复数据成功!",Toast.LENGTH_SHORT).show();
        }
    }

    @Override
    protected void onDestroy()//活动被销毁之前,将数据保存到文件中
    {
        super.onDestroy();
        String string = et.getText().toString();
        save(string);
    }

    /**
     * 将文本数据写入到文件中
     * @param inputText
     */
    private void save(String inputText)
    {
        FileOutputStream fileOutputStream=null;
        BufferedWriter bufferedWriter=null;
        try
        {
            fileOutputStream=openFileOutput("info.txt",MODE_PRIVATE);
            bufferedWriter=new BufferedWriter(new OutputStreamWriter(fileOutputStream));
            bufferedWriter.write(inputText);
        } catch (Exception e)
        {
            System.out.println(e);
        }
        finally
        {
            if (bufferedWriter!=null)
            {
                try
                {
                    bufferedWriter.close();
                } catch (IOException e)
                {
                    System.out.println(e);
                }
            }

        }
    }


    /**
     * 从文件中读取数据
     * @return
     */
    private String load()
    {
        FileInputStream fileInputStream=null;
        BufferedReader bufferedReader=null;
        StringBuilder stringBuilder=new StringBuilder();
        try
        {
            fileInputStream= openFileInput("info.txt");
            bufferedReader=new BufferedReader(new InputStreamReader(fileInputStream));
            String line="";
            while ((line=bufferedReader.readLine())!=null)
            {
                stringBuilder.append(line);
            }
        } catch (Exception e)
        {
            System.out.println(e);
        }
        finally
        {
            if (bufferedReader!=null)
            {
                try
                {
                    bufferedReader.close();
                } catch (IOException e)
                {
                    System.out.println(e);
                }
            }
        }
        return stringBuilder.toString();
    }
}
  1. 布局代码:
<?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/et"
       android:layout_width="match_parent"
       android:layout_height="wrap_content"
       android:gravity="center"
       android:hint="请输入您要保存的信息"/>

四、截图

以下是两张在模拟器中的效果截图。

  1. 输入要保存的文字信息:
    在这里插入图片描述
  2. 文件保存以后,下次再打开程序:
    在这里插入图片描述
<think>首先,用户的问题是:“我想在Android应用开发中使用Android Studio实现本地数据存储的方法 请问Android Studio 本地存储 数据保存方法”。这是一个关于Android开发中本地数据存储的问题。 根据系统级指令: - 所有行内数学表达式必须使用$...$格式。 - 独立公式必须使用$$...$$格式并单独成段。 - LaTeX语法正确。 - 使用中文回答。 - 生成相关问题。 - 在回答中引用的段落末尾自然地添加引用标识,例如[^1]。 - 回答结构清晰,帮助用户逐步解决问题,尽量保证回答真实可靠。 用户可见层的要求是:回答结构清晰,帮助用户逐步解决问题。 参考的站内引用提供了关于Android数据存储的信息: - 引用[1]: 基于Android studio学习安卓数据存储。提到网络数据库方式,但用户问的是本地存储。 - 引用[2]: Android Studio学习笔记——数据库存储。提到文件存储、SharedPreference存储、数据库存储。 - 引用[3]: android studio数据的本地存储并读写。提供文件存储的代码示例。 - 引用[4]: Android studio 存储数据的方法(上)。提供文件存储和Room数据库的代码。 用户的问题明确是关于本地存储的,所以我需要基于这些引用,整理出Android Studio中本地数据存储的方法。 关键本地存储方法: 1. **文件存储(File Storage)**:用于存储文本或二进制文件。 2. **SharedPreferences**:用于存储键值对数据,如用户设置。 3. **SQLite数据库**:用于结构化数据存储。 4. **Room数据库**:一个SQLite的抽象层,更易于使用。 5. **其他**:如存储到外部存储(SD卡),但需要权限。 从引用中: - 引用[2]提到文件存储、SharedPreference存储、数据库存储。 - 引用[3]提供文件存储的读写代码。 - 引用[4]提供文件存储和Room数据库的代码。 我需要构建一个清晰的回答结构: - **介绍**:简要说明Android本地存储的重要性。 - **主要方法**:列出并解释每种方法。 - 文件存储 - SharedPreferences - SQLite数据库 / Room数据库 - **代码示例**:提供简单代码,参考引用。 - **总结**:建议选择方法。 - **相关问题**:生成相关问题。 确保使用中文回答。 添加引用标识:在引用段落末尾添加[^n],基于提供的引用。例如,如果使用引用[3]的代码,添加[^3]。 生成相关问题:在回答末尾添加§§相关问题§§,列出2-3个相关问题。 结构回答: 1. **开头**:直接回答问题,概述方法。 2. **详细解释**: - 文件存储 - SharedPreferences - 数据库存储(包括SQLite和Room) 3. **代码示例**:为每个方法提供简单代码。 4. **结论**:总结建议。 5. **相关问题**:生成相关问题。 使用引用: - 引用[2]:提到三种主要方式。 - 引用[3]:文件存储代码。 - 引用[4]:文件存储和Room代码。 - 引用[1]:提到网络数据库,但用户问本地,所以可能不直接相关,但可以忽略。 在回答中自然地添加引用标识。 最终回答: - 使用中文。 - 结构清晰。 - 生成相关问题。</think>在Android应用开发中,使用Android Studio实现本地数据存储是常见需求。本地存储允许应用在设备上持久化保存数据,无需网络连接,适用于用户设置、缓存或结构化数据。基于参考引用,Android提供了多种本地存储方法,主要包括文件存储、SharedPreferences存储和数据库存储(如SQLite或Room)。以下我将逐步解释每种方法的使用场景、优缺点和实现步骤,并提供代码示例。所有方法均基于Android Studio开发环境,确保代码真实可靠(参考自相关文档和最佳实践)。 ### 1. **文件存储(File Storage)** 文件存储适用于保存文本、二进制文件(如日志、图片或配置文件)。数据存储在应用的内部或外部存储目录中,内部存储默认私有,外部存储可能需要权限。 - **优点**:简单灵活,适合大文件或非结构化数据。 - **缺点**:不适合频繁读写或结构化查询。 - **实现步骤**: - **写入文件**:使用`FileOutputStream`写入内部存储。 - **读取文件**:使用`FileInputStream`读取。 - **代码示例**(参考引用[3]和[4]): ```java // 写入文件(内部存储) public void writeFile(String filename, String data, Context context) { try { FileOutputStream fos = context.openFileOutput(filename, Context.MODE_PRIVATE); fos.write(data.getBytes()); fos.close(); } catch (Exception e) { e.printStackTrace(); } } // 读取文件 public String readFile(String filename, Context context) { try { FileInputStream fis = context.openFileInput(filename); ByteArrayOutputStream baos = new ByteArrayOutputStream(); byte[] buffer = new byte[1024]; int len; while ((len = fis.read(buffer)) != -1) { baos.write(buffer, 0, len); } fis.close(); return baos.toString(); // 返回文件内容 } catch (Exception e) { e.printStackTrace(); return null; } } ``` - **使用场景**:保存用户草稿或配置文件。例如,调用`writeFile("notes.txt", "Hello World", getContext())`写入,再调用`readFile("notes.txt", getContext())`读取[^3][^4]。 - **注意事项**:外部存储需添加`<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />`权限。 ### 2. **SharedPreferences存储** SharedPreferences用于存储键值对(key-value)数据,如用户偏好设置(如主题、登录状态)。数据以XML文件形式存储在`/data/data/<package_name>/shared_prefs/`目录。 - **优点**:轻量级、易用,支持异步操作。 - **缺点**:不适合存储大型或复杂数据(如对象或列表)。 - **实现步骤**: - 获取SharedPreferences实例。 - 使用`Editor`写入数据。 - 直接读取数据。 - **代码示例**(参考引用[2]): ```java // 写入数据 SharedPreferences sharedPref = getSharedPreferences("user_settings", Context.MODE_PRIVATE); SharedPreferences.Editor editor = sharedPref.edit(); editor.putString("username", "user123"); editor.putBoolean("is_logged_in", true); editor.apply(); // 异步提交 // 读取数据 String username = sharedPref.getString("username", "default_user"); boolean isLoggedIn = sharedPref.getBoolean("is_logged_in", false); ``` - **使用场景**:保存用户登录状态或应用设置。例如,在登录页面调用写入,在主页调用读取[^2]。 - **优化**:使用`apply()`替代`commit()`避免UI线程阻塞。 ### 3. **数据库存储(SQLite 或 Room)** 数据库存储适用于结构化数据(如用户信息、列表项),支持复杂查询和事务。Android内置SQLite数据库,但推荐使用Room(一个SQLite抽象层),简化开发。 - **优点**:高效查询、数据一致性,适合大量数据。 - **缺点**:实现较复杂,需定义数据模型。 - **实现步骤**: - **SQLite原生方式**:继承`SQLiteOpenHelper`创建数据库。 - **Room方式**:使用注解定义Entity、DAO和Database(更现代)。 - **代码示例**: - **SQLite原生**(参考引用[2]): ```java public class DBHelper extends SQLiteOpenHelper { private static final String DB_NAME = "user_db"; private static final int DB_VERSION = 1; public DBHelper(Context context) { super(context, DB_NAME, null, DB_VERSION); } @Override public void onCreate(SQLiteDatabase db) { db.execSQL("CREATE TABLE users (id INTEGER PRIMARY KEY, name TEXT)"); } // 写入数据 public void addUser(String name) { SQLiteDatabase db = this.getWritableDatabase(); ContentValues values = new ContentValues(); values.put("name", name); db.insert("users", null, values); db.close(); } // 读取数据 public List<String> getUsers() { List<String> list = new ArrayList<>(); SQLiteDatabase db = this.getReadableDatabase(); Cursor cursor = db.rawQuery("SELECT name FROM users", null); if (cursor.moveToFirst()) { do { list.add(cursor.getString(0)); } while (cursor.moveToNext()); } cursor.close(); return list; } } ``` - **Room方式**(参考引用[4]): - 添加依赖:在`build.gradle`中添加`implementation "androidx.room:room-runtime:2.4.0"`和`annotationProcessor "androidx.room:room-compiler:2.4.0"`。 - 定义Entity、DAO和Database: ```java // Entity(数据模型) @Entity public class User { @PrimaryKey(autoGenerate = true) public int id; public String name; } // DAO(数据访问对象) @Dao public interface UserDao { @Insert void insert(User user); @Query("SELECT * FROM User") List<User> getAll(); } // Database @Database(entities = {User.class}, version = 1) public abstract class AppDatabase extends RoomDatabase { public abstract UserDao userDao(); } // 使用 AppDatabase db = Room.databaseBuilder(context, AppDatabase.class, "user-db").build(); UserDao userDao = db.userDao(); userDao.insert(new User("Alice")); // 写入 List<User> users = userDao.getAll(); // 读取 ``` - **使用场景**:管理用户列表或离线数据。Room简化了SQLite操作,推荐用于新项目[^4]。 ### 总结与建议 - **选择方法**: - 轻量级键值对:用SharedPreferences。 - 文本或文件:用文件存储。 - 结构化数据:优先用Room数据库(更安全高效)。 - **最佳实践**: - 内部存储更安全(外部存储需权限)。 - 异步操作避免UI阻塞(如用`AsyncTask`或协程)。 - 测试数据持久性:重启应用后验证数据是否保留。 - **性能考虑**:文件存储适合低频读写,数据库适合高频查询。根据数据量和复杂度选择,避免过度设计[^2][^4]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值