文件存储

作者: wxyass 分类: Android 发布时间: 2017-03-29 17:11

文件存储

文件存储是 Android 中最基本的一种数据存储方式,它不对存储的内容进行任何的格式化处理,所有数据都是原封不动地保存到文件当中的,因而它比较适合用于存储一些简单的文本数据或二进制数据。如果你想使用文件存储的方式来保存一些较为复杂的文本数据,就需要定义一套自己的格式规范,这样方便于之后将数据从文件中重新解析出来

如何在 Android 项目中使用文件存储的技术

1 新建一个 FilePersistenceTest 项目

2 修改MainActivity 中的代码, 并修改布局activity_main.xml .

import java.io.BufferedWriter;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;

import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.widget.EditText;

public class MainActivity extends Activity {

    private EditText edit;

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

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

    @Override
    protected void onDestroy() {
        super.onDestroy();
        String inputText = edit.getText().toString();
        // (文件内容,文件名称)
        saveFileTxt(inputText, "data");
    }

    /**
     * 保存数据到文件 默认存储到/data/data/<packagename>/files/目录下
     * 
     * @param @param requestData 要保存的字符串
     * @param @param filename 文件名称
     * @return void
     * @throws
     */
    public void saveFileTxt(String requestData, String filename) {
        FileOutputStream out = null;
        BufferedWriter writer = null;
        try {
            // MODE_PRIVATE 默认的操作模式,表示当指定同样文件名的时候,所写入的内容将会覆盖原文件中的内容
            // MODE_APPEND 则表示如果该文件已存在就往文件里面追加内容,不存在就创建新文件。
            out = openFileOutput(filename, Context.MODE_PRIVATE);
            writer = new BufferedWriter(new OutputStreamWriter(out));
            writer.write(requestData);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (writer != null) {
                    writer.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}        

布局文件 activity_main.xml .

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <EditText
        android:id="@+id/edit"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="Type something here" />

</LinearLayout>  

3 运行程序了,输入内容,再按下 Back 键后, 程序退出.

解析:

Context 类中提供了一个 openFileOutput ()方法,可以用于将数据存储到指定的文件中。 openFileOutput ()方法返回的是一个 FileOutputStream 对象,得到了这个对象之后就可以使用 Java 流的方式将数据写入到文件中了。

可以看到, 首先我们在 onCreate()方法中获取了 EditText 的实例, 然后重写了 onDestroy()方法,这样就可以保证在活动销毁之前一定会调用这个方法。在 onDestroy()方法中我们获取了 EditText 中输入的内容,并调用 saveTxt()方法把输入的内容存储到文件中,文件命名为 data.

然后按下 Back 键关闭程序,这时我们输入的内容就已经保存到文件中了。那么如何才能证实数据确实已经保存成功了呢?我们可以借助 DDMS 的 File Explorer 来查看一下。 切换到 DDMS 视 图 , 并 点 击 File Explorer 切 换 卡 , 在 这 里 进 入 到 /data/data/<packagename>/files/目录下,可以看到生成了一个 data 文件

将这个文件导出到电脑上。使用记事本打开这个文件,里面的内容就是你输入的数据.

这样就证实了,在 EditText 中输入的内容确实已经成功保存到文件中了。

不过只是成功将数据保存下来还不够,我们还需要想办法在下次启动程序的时候让这些数据能够还原到 EditText 中,因此接下来我们就要学习一下,如何从文件中读取数据。


从文件中读取数据

修改 MainActivity中的代码

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;

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

public class MainActivity extends Activity {

    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 = readFileTxt("data");
        if (!TextUtils.isEmpty(inputText)) {
            edit.setText(inputText);
            edit.setSelection(inputText.length());
            Toast.makeText(this, "读取成功", 0).show();
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        String inputText = edit.getText().toString();
        // (文件内容,文件名称)
        saveFileTxt(inputText, "data");
    }

    /**
     * 保存数据到文件 默认存储到/data/data/<packagename>/files/目录下
     * 
     * @param @param requestData 要保存的字符串
     * @param @param filename 文件名称
     * @return void
     * @throws
     */
    public void saveFileTxt(String requestData, String filename) {
        FileOutputStream out = null;
        BufferedWriter writer = null;
        try {
            // MODE_PRIVATE 默认的操作模式,表示当指定同样文件名的时候,所写入的内容将会覆盖原文件中的内容
            // MODE_APPEND 则表示如果该文件已存在就往文件里面追加内容,不存在就创建新文件。
            out = openFileOutput(filename, Context.MODE_PRIVATE);
            writer = new BufferedWriter(new OutputStreamWriter(out));
            writer.write(requestData);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (writer != null) {
                    writer.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 从文件中读取数据
     * 
     * @param @param filename 文件名称
     * @return String 返回 String
     * @throws
     */
    public String readFileTxt(String filename) {
        FileInputStream in = null;
        BufferedReader reader = null;
        StringBuilder content = new StringBuilder();
        try {
            in = openFileInput(filename);
            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();
    }
}  

2 运行程序,查看效果

解析:

Context 类中还提供了一个 openFileInput()方法,用于从文件中读取数据。

首先通过 openFileInput()方法获取到了一个 FileInputStream 对象,然后借助它又构建出了一个 InputStreamReader 对象,接着再使用 InputStreamReader 构建出一个 BufferedReader 对象,这样我们就可以通过 BufferedReader 进行一行行地读取,把文件中所有的文本内容全部读取出来并存放在一个 StringBuilder 对象中,最后将读取到的内容返回就可以了。

这里的思路非常简单,在 onCreate()方法中调用 load()方法来读取文件中存储的文本内容,如果读到的内容不为空, 就调用 EditText 的 setText()方法将内容填充到 EditText里,并调用 setSelection 方法将输入光标移动到文本的末尾位置以便于继续输入,然后弹出一句还原成功的提示。

注意在代码中对字符串进行非空判断的时候使用了 TextUtils.isEmpty()方法,这是一个非常好用的方法,它可以一次性进行两种空值的判断。当传入的字符串等于 null 或者等于空字符串的时候,这个方法都会返回 true,从而使得我们不需要单独去判断这两种空值,再使用逻辑运算符连接起来了。

这样我们就已经把文件存储方面的知识学习完了,其实所用到的核心技术就是 Context类中提供的 openFileInput()和 openFileOutput()方法,之后就是利用 Java 的各种流来进行读写操作就可以了


另外:
上面的文件存储,是将文件保存到系统文件中,用户是看不到的,甚至一些程序员都不定知道如何查看, 那么有没有方法将数据保存到内存卡或者本地根目录中呢?

新建一个工具类

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;

import android.os.Environment;

/**
 * 类名称:FileUtil</br> 
 * 类描述:文件工具类</br>
 */
public class FileUtil {

    /**
     * 配合测试把json数据写入文件中(因为数据太大,无法打印全部数据)
     * 
     * @param requestData
     * @param filePath
     */
    public static void writeTxt(String requestData, String filePath) {
        String json = requestData + "\n";
        File file = new File(filePath); // 要写入的文件
        BufferedWriter writer = null;
        try {
            if (!file.exists()) {
                file.createNewFile();
            }
            writer = new BufferedWriter(new FileWriter(file, true));
            writer.newLine();
            writer.write(json);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (writer != null)
                try {
                    writer.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
        }
    }

    /**
     * 将File文件读成String
     * 
     * @param @param filepath 文件路径,如:/sdcard/test.txt
     * @return String 返回类型
     * @throws
     */
    public static String file2String(String filepath) {

        String str = "";
        try {
            String encoding = "UTF-8";
            File urlFile = new File(filepath);
            if (urlFile.isFile() && urlFile.exists()) { // 判断文件是否存在
                InputStreamReader isr = 
                    new InputStreamReader(new FileInputStream(urlFile), encoding);
                BufferedReader br = new BufferedReader(isr);
                String mimeTypeLine = null;
                while ((mimeTypeLine = br.readLine()) != null) {
                    str = str + mimeTypeLine;
                }
            } else {
                System.out.println("找不到指定的文件");
            }
        } catch (Exception e) {
            System.out.println("读取文件内容出错");
            e.printStackTrace();
        }
        return str;
    }

    /**
     * 获取sd卡路径
     * 
     * @return
     */
    public static String getSDPath() {

        File sdDir = null;

        // 判断sd卡是否存在
        boolean sdCardExist = Environment.getExternalStorageState()
                .equals(android.os.Environment.MEDIA_MOUNTED); 

        if (sdCardExist) // 如果SD卡存在,则获取跟目录
        {
            sdDir = Environment.getExternalStorageDirectory();// 获取跟目录
        }
        return sdDir.toString();
    }
}  

添加权限:

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>  

在MainActivity中调用工具类方法,读写文件.

import android.app.Activity;
import android.os.Bundle;
import android.text.TextUtils;
import android.widget.EditText;
import android.widget.Toast;

import com.yassblog.utils.FileUtil;

public class MainActivity extends Activity {

    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 = FileUtil.file2String(FileUtil.getSDPath()+"/ceshi1.txt");
        if (!TextUtils.isEmpty(inputText)) {
            edit.setText(inputText);
            edit.setSelection(inputText.length());
            Toast.makeText(this, "读取成功", 0).show();
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        String inputText = edit.getText().toString();
        // 保存数据 (文件内容,文件路径)
        FileUtil.writeTxt(inputText, FileUtil.getSDPath()+"/ceshi1.txt");
    }
}  

如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!

发表评论

您的电子邮箱地址不会被公开。 必填项已用*标注