一、openFileOutput和openFileInput
Context提供了如下两个方法来打开本应用程序的数据文件夹里的文件I/O流。
》FileInputStream openFileInput(String name):打开应用程序的数据文件夹下的name文件对应输入流。
》FileOutputStream openFileOutput(String name, int mode):打开应用程序的数据文件夹下的name文件对应输入流。
上面两个方法分别用于打开文件输入流、输出流,其中第二个方法的第二个参数指定打开文件的模式,该模式支持如下值。
》MODE_PRIVATE:该文件只能被当前程序读写。
》MODE_APPEND:以追加方式打开该文件,应用程序可以向该文件中追加内容。
》MODE_WORLD_READABLE:该文件的内容可以被其他程序读取。
》MODE_WORLD_WRITEABLE:该文件的内容可由其他程序读、写。
除此之外,Context还提供了如下几个方法来访问应用程序的数据文件夹。
》getDir(String name, int mode):在应用程序的数据文件夹下获取或创建name对应的子目录。
》File getFilesDir():获取该应用程序的数据文件夹的绝对路径。
》String[] fileList():返回该应用程序的数据文件夹下的全部文件。
》deleteFile(String name):删除该应用程序的数据文件夹下的指定文件。
下面是一个简单的用openFileOutput和openFileInput读、写文件的demo
1、Activity文件
package com.example.androidioanddatastore.sdcode;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintStream;
import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import com.example.androidioanddatastore.R;
/**
* 使用openFileOutput和openFileInput读、取文件的例子
* @author Administrator
*
*/
public class FileActivity extends Activity {
public final static String FILE_NAME = "file_data.bin";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_file);
System.out.println(new StringBuffer("a").append("b").append("c").toString());
//获取两个按钮
Button readBtn = (Button) findViewById(R.id.read_btn);
Button writeBtn = (Button) findViewById(R.id.write_btn);
//获取两个文本框
final EditText readEdit = (EditText) findViewById(R.id.read_edit);
final EditText writeEdit = (EditText) findViewById(R.id.write_edit);
//为writeBtn按钮绑定监听器
writeBtn.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
//将writeEdit的内容写入文件中
write(writeEdit.getText().toString());
writeEdit.setText("");
}
});
//为readBtn按钮绑定监听器
readBtn.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
//读取指定文件中的内容,并显示出来
readEdit.setText(read());
}
});
}
protected String read() {
try {
//打开输入流
FileInputStream fileInputStream = openFileInput(FILE_NAME);
byte[] buff = new byte[2048];
int hasRead = 0;
StringBuilder builder = new StringBuilder("");
//读取文件内容
while ((hasRead = fileInputStream.read(buff)) > 0) {
builder.append(new String(buff , 0 , hasRead));
}
//关闭输入流
fileInputStream.close();
return builder.toString();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
private void write(String content){
try {
//以追加模式打开输入流
FileOutputStream fileOutputStream = openFileOutput(FILE_NAME, Context.MODE_APPEND);
//将FileOutputStream包装成PaintStream
PrintStream printStream = new PrintStream(fileOutputStream);
//输出文件内容
printStream.println(content);
//关闭输入流
printStream.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
}
2、布局文件
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<EditText
android:id="@+id/read_edit"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1" />
<Button
android:id="@+id/read_btn"
android:layout_width="match_parent"
android:layout_height="40dp"
android:text="read" />
<EditText
android:id="@+id/write_edit"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1" />
<Button
android:id="@+id/write_btn"
android:layout_width="match_parent"
android:layout_height="40dp"
android:text="write" />
</LinearLayout>
当输入的内容保存到应用程序的数据文件夹中后,打开File Explorer面板后,可以在/data/data/<package name>/files目录下找到保存的文件。
二、读取SD卡上的文件
为了更好的存、取应用程序的大文件数据,应用程序需要读、写SD卡上的文件。SD卡大大扩充手机的存储能力。
读、写SD上的文件请按如下步骤进行。
(1)调用Environment的getExternalStorageState()方法判断手机上是否插入了SD卡,并且应用程序具有读写SD卡的权限。例如使用如下代码:
// 如果手机插入了SD卡,而且应用程序具有访问SD卡的权限
Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)
(2)调用Environment的getExternalStorageDirectory()方法来获取外部存储器,也就是SD卡的目录。
(3)使用FileInputStream、FileOutputStream、FileReader或FIleWriter读、写SD卡里的文件。
应用程序读、写SD卡的文件有如下两个注意点:
》手机上应该已插入SD卡。对于模拟器来说,可通过mksdcord命令来创建虚拟存储卡。
》为了读、写SD卡上的数据,必须在应用程序的清单文件中添加读、写SD卡的权限。例如如下配置:
<!-- 在SD卡中创建与删除文件的权限 -->
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>
<!-- 向SD卡写入数据权限 -->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
下面的demo示范了如何读、写SD卡上的文件。这个demo的布局文件与上一个demo完全一样。
package com.example.androidioanddatastore.sdcode;
import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.RandomAccessFile;
import com.example.androidioanddatastore.R;
import android.app.Activity;
import android.os.Bundle;
import android.os.Environment;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
public class SDCodeActivity extends Activity {
public final static String FILE_NAME = "/file_data.bin";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_file);
System.out.println(new StringBuffer("a").append("b").append("c")
.toString());
// 获取两个按钮
Button readBtn = (Button) findViewById(R.id.read_btn);
Button writeBtn = (Button) findViewById(R.id.write_btn);
// 获取两个文本框
final EditText readEdit = (EditText) findViewById(R.id.read_edit);
final EditText writeEdit = (EditText) findViewById(R.id.write_edit);
// 为writeBtn按钮绑定监听器
writeBtn.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// 将writeEdit的内容写入文件中
write(writeEdit.getText().toString());
writeEdit.setText("");
}
});
// 为readBtn按钮绑定监听器
readBtn.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// 读取指定文件中的内容,并显示出来
readEdit.setText(read());
}
});
}
protected String read() {
try {
// 如果手机插入了SD卡,而且应用程序具有访问SD卡的权限
if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
// 获取SD卡目录
File sdCodeDir = Environment.getExternalStorageDirectory();
FileInputStream fileInputStream = new FileInputStream(sdCodeDir.getCanonicalPath() + FILE_NAME);
//将指定输入流包装成BufferedReader
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(fileInputStream));
StringBuilder builder = new StringBuilder("");
String line = "";
//循环读取内容
while ((line = bufferedReader.readLine()) != null) {
builder.append(line);
}
//关闭输入流
bufferedReader.close();
return builder.toString();
}
} catch (IOException e) {
}
return null;
}
protected void write(String content) {
try {
// 如果手机插入了SD卡,而且应用程序具有访问SD卡的权限
if (Environment.getExternalStorageState().equals(
Environment.MEDIA_MOUNTED)) {
// 获取SD卡目录
File sdCodeDir = Environment.getExternalStorageDirectory();
File targetFile = new File(sdCodeDir.getCanonicalPath()
+ FILE_NAME);
// 以指定文件创建RandomAccessFile对象
RandomAccessFile accessFile = new RandomAccessFile(targetFile,
"rw");
// 将文件记录指针移动最后
accessFile.seek(targetFile.length());
// 输出文件内容
accessFile.write(content.getBytes());
// 关闭RandomAccessFile
accessFile.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
提示:
如果不想使用Environment.getExternalStorageDirectory()这么复杂的语句来获取SD卡的路径,完全可以使用/mnt/sdcard/路径代表SD卡的路径,然后程序通过判断/mnt/sdcard/路径是否存在就可知道手机是否已经插入SD卡。
SD卡文件浏览器
下面是利用Java的File类开发一个SD卡文件浏览器,该程序直接使用/mnt/sdcard/来访问系统的SD卡目录,然后通过File的listFiles()方法来获取指定目录下的全部文件和文件夹。
1.程序的布局文件:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<!-- 显示当前路径的文本框 -->
<TextView
android:id="@+id/explorer_path"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"/>
<!-- 列出当前路径下的所有文件的ListView -->
<ListView
android:id="@+id/explorer_listview"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:divider="#000"
android:dividerHeight="1dp"/>
<!-- 返回上一级目录的按钮 -->
<Button
android:id="@+id/explorer_parent"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/ic_menu_back"
/>
</LinearLayout>
2.item文件
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal" >
<ImageView
android:id="@+id/item_explorer_icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<TextView
android:id="@+id/item_explorer_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</LinearLayout>
3.activity文件
package com.example.androidioanddatastore.sdcode;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.Button;
import android.widget.ListView;
import android.widget.SimpleAdapter;
import android.widget.TextView;
import android.widget.Toast;
import com.example.androidioanddatastore.R;
/***
* SD卡文件浏览器demo
*
* @author Administrator
*
*/
public class SDFileExplorerActivity extends Activity {
public final static String SDFilePath = "/mnt/sdcard/";
/** 显示内容的ListView */
private ListView mListView;
/** 显示当前的目录路径 */
private TextView mTextView;
/** 返回上一级按钮 **/
private Button mBtn;
/** 记录当前的父文件夹 */
private File currentParent;
/** 记录当前目录下的所有文件的文件数组 */
private File[] currentFiles;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_sd_file_explorer);
// 初始化组件
initView(this);
// 初始化源数据
initData(this);
// 为组件绑定事件监听器
initEvent();
}
/**
* 初始化事件监听器
*/
private void initEvent() {
// 为ListView列表项绑定点击事件监听器
mListView.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
// 用户点击了文件,直接返回,不做任何处理
if (currentFiles[position].isFile()) {
return;
}
// 获取用户单击的文件夹下的所有文件
File[] tmp = currentFiles[position].listFiles();
if (tmp == null || tmp.length <= 0) {
Toast.makeText(SDFileExplorerActivity.this,
"当前路径不可访问或该路径下没有文件", Toast.LENGTH_SHORT).show();
} else {
// 获取用户单击的列表项对应的文件夹,设为当前的父文件夹
currentParent = currentFiles[position];
// 保存当前的文件夹内的全部文件和文件夹
currentFiles = tmp;
// 再次更新ListView
inflateListView(tmp);
}
}
});
mBtn.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
try {
if (!currentParent.getCanonicalPath().equals(SDFilePath)) {
//获取上级目录
currentParent = currentParent.getParentFile();
//列出当前目录下的所有文件
currentFiles = currentParent.listFiles();
//再次更新ListView
inflateListView(currentFiles);
}
} catch (IOException e) {
e.printStackTrace();
}
}
});
}
/***
* 初始化数据
*
* @param context
*/
private void initData(Context context) {
// 获得系统的SDCode的目录
File root = new File(SDFilePath);
// 如果文件夹存在,即SD卡存在
if (root.exists()) {
currentParent = root;
// 获取root文件夹下的所有文件
currentFiles = root.listFiles();
// 使用当前目录下的全部文件、文件夹来填充ListView
inflateListView(currentFiles);
}
}
/**
* 填充ListView数据
*
* @param currentFiles
* File[]数据
*/
private void inflateListView(File[] files) {
// 创建一个List集合,List集合的元素是Map
List<Map<String, Object>> listItems = new ArrayList<Map<String, Object>>();
for (int i = 0; i < files.length; i++) {
Map<String, Object> listItem = new HashMap<String, Object>();
// 判断当前File是文件夹,使用文件夹图标;否则使用文件图标
if (files[i].isDirectory()) {
listItem.put("icon", R.drawable.ic_menu_copy);
} else {
listItem.put("icon", R.drawable.ic_menu_copy_holo_light);
}
// 保存文件夹或者文件的name
listItem.put("fileName", files[i].getName());
// 添加List项
listItems.add(listItem);
}
// 创建一个SimpleAdapter
SimpleAdapter adapter = new SimpleAdapter(SDFileExplorerActivity.this,
listItems, R.layout.item_files_explorer, new String[] { "icon",
"fileName" }, new int[] { R.id.item_explorer_icon,
R.id.item_explorer_name });
// 为ListView设置Adapter
mListView.setAdapter(adapter);
runOnUiThread(new Runnable() {
@Override
public void run() {
try {
mTextView.setText("当前路径为:"
+ currentParent.getCanonicalPath());
} catch (IOException e) {
e.printStackTrace();
}
}
});
}
/***
* 初始化组件
*
* @param context
*/
private void initView(Context context) {
mListView = (ListView) findViewById(R.id.explorer_listview);
mTextView = (TextView) findViewById(R.id.explorer_path);
mBtn = (Button) findViewById(R.id.explorer_parent);
}
}