最近学习了android关于文件存储的一些知识,这里记录一下。
ps:本人是android初学者,文中若有说的不对,欢迎各位大神指出。

android提供了三种简单的数据保存技术,本篇主要记录有关文件存储的方式

文件字节输出流对文件写操作

/**文件字节输出流对文件写操作
     * @param filename 需要写入的文件名字,如果没有会自动创建一个
     * @param saveText 需要保存的字符串
     * filename是文件的名字,不需要加入路径,eg.
     *                 String filename = "login"
     * openFileOutput方法,指定且不能修改的路径:
     *                 /data/data/<包名>/files
     *  调用此方法,仅需要传入文件名而不用指定路径
     *  通过FileOutputStream.write写数据的时候,数据首先是存放在缓冲区的,当缓冲区满的时候向文件
     *  写入数据,在调用close()之前需要调用flush()方法,作用是把当前缓冲区的数据全部写入到文件中
     *  如果没有flush(),会有部分少量数据在缓冲区里面没有写入文件,直接close就会导致这些数据丢失
     *  此方法是覆盖式写法
     */
    public void write_of_FileOutputStream(String filename,String saveText){
        FileOutputStream fos = null;
        try {
            fos = openFileOutput(
                    filename,
                    MODE_PRIVATE                //
            );                                    //返回一个FileOutputStream 对象
            fos.write(saveText.getBytes());
            fos.flush();                          //清空缓冲区,把缓冲区里面的数据写入文件,此句必须加
        }catch (IOException e){
            e.printStackTrace();
        }finally {
            if (fos!=null){
                try{
                    fos.close();
                }catch (IOException e){
                    e.printStackTrace();
                }
            }
        }
    }

在这里,首先通过openFileOutput()方法,获取一个FileOutputStream对象,然后通过这个对象,调用write()方法写入数据。注意,利用FileOutputStream来写入数据,数据先是放在缓冲区里面,当缓冲区满了,才会写入到文件里面,所以这里必须调用flush()方法,用来清空缓冲区,把缓冲区里面的数据全部写入文件,然后才可以close(),否则可能会出现部分数据没有写入文件。由于是字节写入,在write的时候需要把字符串转换成字节,通过字符串的getBytes方法。

文件字节输入流对文件读操作

/**文件字节输入流对文件读操作
     * @param filename    需要读取的文件名字
     * @return content 以字符串形式得到文件中的内容
     */
    public String read_of_FileInputStream(String filename){
        FileInputStream fis = null;
        byte[] buffer = null;
        String content="";
        try {
//            File file = new File(pathfile);
//            fis = new FileInputStream(file);
            fis = openFileInput(filename);          //获得文件输入流,也可以使用上面两句指定路径
            buffer = new byte[fis.available()];     //通过avilable方法得到文件大小
            fis.read(buffer);                        //从输入流中读取数据
            content = new String(buffer);
        }catch (IOException e){
            e.printStackTrace();
        }finally {
            if (fis!=null){
                try {
                    fis.close();
                }catch (IOException e){
                    e.printStackTrace();
                }
            }
        }
        return content;
    }

与字节输出流的FileOutputStream对应的字节输入流FileInputStream方法, 也是有默认的路径,所以这里只需要给出文件名而不能给出具体的路径。这一段代码,利用字节数组byte[] buffer来保存读到的数据,为了不浪费内存空间,在读取操作之前,调用available()方法,可以获得文件的大小,注意:此方法只有在一开始文件没有读写,光标在开头的时候调用才可以返回文件的大小。用得到的具体大小来构造一个字节数组,节省内存空间。最后通过字符串的构造函数把字节数组转换成为字符串返回。

文件字符输出流对文件写操作

/**文件字符输出流对文件写操作
     * @param pathfile 需要写入的文件名字(带路径),如果没有会自动创建一个
     * @param saveText 需要保存的字符串
     * pathfile是一个完整的文件路径,eg.
     *                 String pathfile = "/data/data/com.example.asus.savedata/files/login"
     *  此方法是覆盖式写法
     */
    public void write_of_FileWriter(String pathfile,String saveText){
        FileWriter writer=null;
        try {
            File file = new File(pathfile);
            writer = new FileWriter(file);
            writer.write(saveText);
            writer.flush();
        }catch (IOException e){
            e.printStackTrace();
        }finally {
            if (writer!=null){
                try{
                    writer.close();
                }catch (IOException e){
                    e.printStackTrace();
                }
            }
        }
    }

这一段代码,通过字符输出流的方式写入文件。首先创建一个File对象,这里用的是具体的路径+文件名来实例化这个File对象,然后利用这个File对象构造出一个FileWriter对象,通过这个File Writer对象来进行读写

文件字符输入流对文件读操作

/**文件字符输入流对文件读操作
     * @param pathfile 需要读入的文件名字(带路径)
     * @return content.toString 以字符串形式得到文件中的内容
     */
    public String read_of_FileReader(String pathfile){
        StringBuilder content = new StringBuilder();
        FileReader reader=null;
        try {
            File file = new File(pathfile);     //通过路径打开文件
            reader = new FileReader(file);      //利用File对象创建reader对象

            //进行读取操作 每次读取单个字符
//            int read_char =reader.read();
//            //如果读取完毕,返回-1
//            while (read_char!=-1){
//                //使用StringBuilder拼接字符串,比使用String相加可以节省内存浪费
//                //必须要把read_char转换成char类型
//                content.append((char)read_char);
//                //读取下一个字符
//                read_char = reader.read();
//            }

            //进行读取操作 读取一个字符数组然后转换成字符串
            char[] chs =new char[(int)file.length()];   //使用file的length方法获取文件的大小,为了节省空间
            reader.read(chs);
            content.append(String.valueOf(chs));

        }catch (IOException e){
            Toast.makeText(this, "error", Toast.LENGTH_SHORT).show();
            e.printStackTrace();
        }finally {
            if (reader!=null){
                try {
                    reader.close();
                }catch (IOException e){
                    e.printStackTrace();
                }
            }
        }

        return content.toString();
    }

这部分代码与上面的类似,在里面我写了两种读的方式,一个是按照单字符读入(注释部分),一个是读取字符数组的方式。这里说一下,按照单个字符读入的方式,首先创建一个StringBuilder 对象,通过append的方法来拼接字符串,这里不使用String对象的相加,因为我们都知道如果用String字符串的相加会造成内存空间的大量浪费。而第二种方法,是创建一个字符数组,然后一次性读取到这个字符数组中。这里面字符数组的大小很关键,如果你构建一个100大小的字符数组,即使你读取的文件是空的,你返回的字符串实际上也是占用了100大小的空间,用length看一下你就知道。所以这里在构建字符数组的使用,通过File的length方法,得到文件的大小,用这个大小来创建字符数组。

缓冲输出流对文件写操作

/**缓冲输出流对文件写操作
     * @param filename 需要写入的文件名字,如果没有会自动创建一个
     * @param saveText 需要保存的字符串
     * filename是文件的名字,不需要加入路径,eg.
     *                 String filename = "login"
     * openFileOutput方法,指定且不能修改的路径:
     *                 /data/data/<包名>/files
     *  调用此方法,仅需要传入文件名而不用指定路径
     *  此方法是覆盖式写法
     */
    public void write_of_BufferedWriter(String filename,String saveText){
        FileOutputStream outputStream;
        BufferedWriter writer = null;
        try {
            outputStream = openFileOutput(
                    filename,
                    MODE_PRIVATE
                    );
            writer = new BufferedWriter(new OutputStreamWriter(outputStream));
            writer.write(saveText);
        }catch (IOException e){
            e.printStackTrace();
        }finally {
            try {
                if (writer!=null){
                    writer.close();
                }
            }catch (IOException e){
                e.printStackTrace();
            }
        }
    }

这一段代码也很好理解,首先是通过openFileOutput返回一个FileOutputStream对象,用这个对象构建一个OutputStreamWriter对象,再通过OutputStreamWriter对象构建出BufferedWriter对象,然后通过BufferedWriter的方法来操作文件。

缓冲输入流对文件读操作

/**缓冲输入流对文件读操作
     * @param filename    需要读取的文件名字
     * @return content.toString 以字符串形式得到文件中的内容
     */
    public String read_of_BufferedReader(String filename){
        FileInputStream inputStream =null;
        BufferedReader reader = null;
        StringBuilder content = new StringBuilder();        //使用字符串拼接,节省内存
        try {
            inputStream = openFileInput(filename);
            reader = new BufferedReader(new InputStreamReader(inputStream));
            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();
    }

和上面的写入差不多,这里不再多说。