Android的文件读写与JavaSE的文件读写相同,都是使用IO流。但是由于Android的权限机制,不能直接用java的api来读写文件,因为java的io函数没有提这个机制 。如果要打开程序自己私有的文件和数据,那必须使用Activity提供openFileOutput和openFileInput方法。

其中openFileOutput()方法的第二参数用于指定操作模式,有四种模式,分别为: Context.MODE_PRIVATE = 0 Context.MODE_APPEND = 32768 Context.MODE_WORLD_READABLE = 1 Context.MODE_WORLD_WRITEABLE = 2

  • Context.MODE_PRIVATE:为默认操作模式,代表该文件是私有数据,只能被应用本身访问,在该模式下,写入的内容会覆盖原文件的内容,如果想把新写入的内容追加到原文件中。可以使用Context.MODE_APPEND
  • Context.MODE_APPEND:模式会检查文件是否存在,存在就往文件追加内容,否则就创建新文件。该模式也是私有数据,只能被应用本身访问。 Context.MODE_WORLD_READABLE和Context.MODE_WORLD_WRITEABLE用来控制其他应用是否有权限读写该文件。

可以使用+连接这些权限 : 例如如果希望文件被其他应用读和写,可以传入: openFileOutput(“filename.txt”, Context.MODE_WORLD_READABLE + Context.MODE_WORLD_WRITEABLE);

Activity还提供了getCacheDir()和getFilesDir()方法: getCacheDir()方法用于获取/data/data//cache目录(一些临时文件可以放在缓存目录用完了就删了) getFilesDir()方法用于获取/data/data//files目录

下面我们看一个文件读写的例子,运行效果如下:

布局文件如下:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >

    <TextView
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="@string/tv_filename" />

    <EditText
        android:id="@+id/et_filename"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:inputType="text" />

    <TextView
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="@string/tv_filecontent" />

    <EditText
        android:id="@+id/et_filecontent"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:minLines="3" />

    <LinearLayout
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal" >

        <Button
            android:id="@+id/btn_Save"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="@string/btn_save" />

        <Button
            android:id="@+id/btn_Read"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="@string/btn_read" />
    </LinearLayout>

    <LinearLayout
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal" >

        <Button
            android:id="@+id/btn_Save2SDCard"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="@string/btn_save2SDCard" />

        <Button
            android:id="@+id/btn_ReadFromSDCard"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="@string/btn_readfromSDCard" />
    </LinearLayout>

    <Button
        android:id="@+id/btn_exit"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="@string/btn_exit" />

</LinearLayout>

我们的项目中可能会经常需要用到文件读写操作,同样也是为了MVC模式,我们可以把文件操作的代码放在一个文件操作类中:

package com.liuzhichao.file;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;

import org.apache.http.util.EncodingUtils;

import android.content.Context;
import android.os.Environment;

public class FileUtils {

	public static String SDPATH = null; // sd卡路径
	public static boolean isSdCardExist = false; // sd卡是否存在

	private Context context;

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

	public FileUtils() {
		isSdCardExist = Environment.getExternalStorageState().equals(
				android.os.Environment.MEDIA_MOUNTED); // 判断sd卡是否存在
		if (isSdCardExist) {
			SDPATH = Environment.getExternalStorageDirectory() + File.separator;
		}

	}

	public FileUtils(Context context) {
		this.context = context;
	}

	/**
	 * 保存文件
	 * @param name      文件名称
	 * @param content   文件内容
	 * @param mode      权限
	 * @throws IOException
	 */
	public void writeFile(String name, String content, int mode)
			throws IOException {
		FileOutputStream outputStream = context.openFileOutput(name, mode);
		outputStream.write(content.getBytes());
		outputStream.close();
	}

	/**
	 * 保存文件,默认权限为私有
	 * @param name      文件名称
	 * @param content   文件内容
	 * @throws IOException
	 */
	public void writeFile(String name,String content) throws IOException{
		writeFile(name,content,Context.MODE_PRIVATE);
	}

	/**
	 * 读取文件
	 * @param name  文件名称
	 * @throws IOException
	 */
	public String readFile(String name) throws IOException{
		FileInputStream inputStream = context.openFileInput(name);
		return streamRead(inputStream);
	}

	/**
	 * 保存文件到SDCard根目录
	 * @param name     文件名称
	 * @param content  文件内容
	 * @throws IOException
	 */
	public void writeFileToSDCard(String name, String content) throws IOException{
		writeFileToSDCard("",name,content);
	}

	/**
	 * 保存文件到SDCard指定目录
	 * @param path
	 * @param name
	 * @param content
	 * @throws IOException
	 */
	public void writeFileToSDCard(String path,String name, String content) throws IOException{
		File file = new File(SDPATH+path,name);
		FileOutputStream outputStream = new FileOutputStream(file);
		outputStream.write(content.getBytes());
		outputStream.close();
	}

	/**
	 *  从SDCard指定目录中读取文件
	 * @param path
	 * @param name
	 * @return
	 * @throws IOException
	 */
	public String readFileFromSDCard(String path,String name) throws IOException{
		File file = new File(SDPATH+path,name);
		FileInputStream inputStream = new FileInputStream(file);
		return streamRead(inputStream);
	}

	/**
	 *  从SDCard根目录中读取文件
	 * @param path
	 * @param name
	 * @return
	 * @throws IOException
	 */
	public String readFileFromSDCard(String name) throws IOException{
		return readFileFromSDCard("",name);
	}

	/**
	 * 从流中读取数据
	 * @param inputStream
	 * @return
	 * @throws IOException
	 */
	private String streamRead(InputStream inputStream) throws IOException {  
        int buffersize = inputStream.available();// 取得输入流的字节长度  
        byte buffer[] = new byte[buffersize];  
        inputStream.read(buffer);// 将数据读入数组  
        inputStream.close();     // 读取完毕后要关闭流。  
        String result = EncodingUtils.getString(buffer, "UTF-8");// 设置取得的数据编码,防止乱码  
        return result;  
    }  
}

再来看一下FileDemoActivity.java

package com.liuzhichao.file;

import java.io.IOException;

import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;

public class FileDemoActivity extends Activity {

	private EditText et_FileName;
	private EditText et_FileContent;
	private Button btn_save;
	private Button btn_read;
	private Button btn_saveToSDCard;
	private Button btn_readFileFromSDCard;
	private Button btn_exit;
	private FileUtils fileUtils;
	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);
		findViews();
		eventeHandler();
	}

	private void findViews() {
		et_FileName = (EditText) findViewById(R.id.et_filename);
		et_FileContent = (EditText) findViewById(R.id.et_filecontent);
		btn_save = (Button) findViewById(R.id.btn_Save);
		btn_read = (Button) findViewById(R.id.btn_Read);
		btn_saveToSDCard = (Button) findViewById(R.id.btn_Save2SDCard);
		btn_readFileFromSDCard = (Button)findViewById(R.id.btn_ReadFromSDCard);
		btn_exit = (Button)findViewById(R.id.btn_exit);
	}

	private void eventeHandler() {

		//保存文件事件处理
		btn_save.setOnClickListener(new OnClickListener() {
			public void onClick(View v) {
				//获取文件名和文件内容
				String name = et_FileName.getText().toString();
				String content = et_FileContent.getText().toString();
				//实例化文件操作类
				fileUtils = new FileUtils(getApplicationContext());
				//文件名称和文件内容不能为空
				if ("".equals(name) && "".equals(content)) {
					Toast.makeText(getApplicationContext(), "请输入文件名称和文件内容", 1)
							.show();
					return;
				}
				try {
					//保存文件
					fileUtils.writeFile(name, content);
					Toast.makeText(getApplicationContext(), "文件写入成功", 1).show();
				} catch (IOException e) {
					e.printStackTrace();
					Toast.makeText(getApplicationContext(), "文件写入失败", 1).show();
				}
			}
		});

		//读取文件
		btn_read.setOnClickListener(new OnClickListener() {

			public void onClick(View v) {
				fileUtils = new FileUtils(getApplicationContext());
				String name = et_FileName.getText().toString();
				if ("".equals(name)) {
					Toast.makeText(getApplicationContext(), "请输入文件名称", 1)
							.show();
					return;
				}
				try {
					String content = fileUtils.readFile(name);
					if ("".equals(content) && content == null) {
						Toast.makeText(getApplicationContext(), "文件读取失败", 1)
								.show();
						return;
					}
					et_FileContent.setText(content);
				} catch (IOException e) {
					e.printStackTrace();
					Toast.makeText(getApplicationContext(), "文件读取失败", 1).show();
				}
			}
		});

		//保存文件到sd卡
		btn_saveToSDCard.setOnClickListener(new OnClickListener() {
			public void onClick(View v) {
				fileUtils = new FileUtils();
				String name = et_FileName.getText().toString();
				String content = et_FileContent.getText().toString();
				if ("".equals(name) && "".equals(content)) {
					Toast.makeText(getApplicationContext(), "请输入文件名称和文件内容", 1)
							.show();
					return;
				}
				try {
					fileUtils.writeFileToSDCard(name, content);
					Toast.makeText(getApplicationContext(), "文件写入成功", 1).show();
				} catch (IOException e) {
					e.printStackTrace();
					Toast.makeText(getApplicationContext(), "文件写入失败", 1).show();
				}
			}
		});

		//从sd卡中读取文件
		btn_readFileFromSDCard.setOnClickListener(new OnClickListener() {

			public void onClick(View v) {
				fileUtils = new FileUtils();
				String name = et_FileName.getText().toString();
				if ("".equals(name)) {
					Toast.makeText(getApplicationContext(), "请输入文件名称", 1)
							.show();
					return;
				}
				try {
					String content = fileUtils.readFileFromSDCard(name);
					if ("".equals(content) && content == null) {
						Toast.makeText(getApplicationContext(), "文件读取失败", 1)
								.show();
						return;
					}
					et_FileContent.setText(content);
				} catch (IOException e) {
					e.printStackTrace();
					Toast.makeText(getApplicationContext(), "文件读取失败", 1).show();
				}
			}
		});

		//退出
		btn_exit.setOnClickListener(new OnClickListener() {
			public void onClick(View v) {
				finish();
			}
		});
	}
}

需要特别说明的是,对SDCard进行操作的时候一定要声明权限。

<!-- 往SDCard写入数据权限 -->
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <!-- 在SDCard中创建与删除文件权限 -->
    <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />