Android学习笔记十四.Android数据存储与IO.SD卡的读写实例

    当程序通过Context的openFileInput或openFileOutput来打开文件输入流、输出流时,程序所打开的都是应用程序的数据文件夹里的文件(即手机内置的存储空间)。为了更好地存、取应用程序的打文件数据,应用程序需要读、写SD卡上的文件。
转载请表明出处:http://blog.csdn.net/u012637501(嵌入式_小J的天空)
一、读、写SD卡上的文件开发思路
1.调用Environment的getExternalStorageState()方法判断手机是否插入了SD卡,并却应用程序具有读写SD卡的权限;
Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED);
注释:如果手机已插入SD卡,且应用程序具有读写SD卡的能力,则返回为true.
2.获取SD卡的根目录。调用Environment的getExternalStorageDirectory()方法来获取外部存储器(SD卡)的根目录
File sdCardDir=Environment.getExternalStorageDirectory();
3.使用FileInputStream、FileOutputStream(以字节为单位);FileReader或FileWriter(以字符为单位)读、写SD卡里的文件
读文件数据举例
File sdCardDir=Environment.getExternalStorageDirectory();
FileInputStream fis=new FileInputStream(sdCardDir.getCanonicalPath()+FILE_NAME);
BufferedReader br=new BufferedReader(new InputStreamReader(fis));     //将指定输入流包装成BufferedReader
StringBuilder sb=new StringBuilder("");
String line=null; 
while((line=br.readLine())!=null)
{
     sb.append(line);
 }
 br.close(); 
 return sb.toString();
写数据到文件举例
File sdCardDir=Environment.getExternalStorageDirectory();
File targetFile=new File(sdCardDir.getCanonicalPath()+"testfile.txt"); //在指定路径下实例化一个File对象
RandomAccessFile raf=new RandomAccessFile(targetFile,"rw");  //以指定文件创建RandomAccessFile对象,向SD卡指定文件追加内容(targetFile为一个文件对象)
raf.seek(targetFile.length()); //将文件记录指针移动到最后
raf.write(content.getBytes());
raf.close();
4.在应用程序的清单文件(AndroidManifest.xml)中添加读、写SD卡的权限
    <!-- 在SD卡中创建与删除文件权限 -->
    <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>
    <!-- 向SD卡写入数据权限 -->
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
5.实例源码
实现:在SD卡路径/mnt/sdcard/目录下创建一个testfile.txt文件(不存在时自动创建),向该文件读、写数据。
package com.example.android.sdcard_2;
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 android.support.v7.app.ActionBarActivity;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;
import android.os.Bundle;
import android.os.Environment;
public class MainActivity extends ActionBarActivity {
 final String FILE_NAME="/testfile.txt";
 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.main);
  //获取组件:两个按钮、两个文本
  Button write=(Button)findViewById(R.id.writeButton);
  Button read=(Button)findViewById(R.id.readButton);
  final EditText edit2=(EditText)findViewById(R.id.writetext);
  final EditText edit1=(EditText)findViewById(R.id.readtext);
 
 //1.写数据到SD卡文件中
  write.setOnClickListener(new OnClickListener(){
     @Override
     public void onClick(View v) {
      write(edit2.getText().toString());	//获取文本框中的数据并写到SD卡的文件中
      edit2.setText(""); //清空文本框
     }
     
    });
 //2.为读取SD卡按钮绑定事件监听器
  read.setOnClickListener(new OnClickListener(){
   @Override
   public void onClick(View v) {
    edit1.setText(read());	 //读取SD卡文件数据到文本框中
   }
  });
 
 }
 //3.成员函数:实现写SD卡模块,如果手机插入了SD卡,而且应用程序具有访问SD的权限
 private void write(String content) {
  try{
   if(Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED))//判断手机是否插入SD卡
   {
    //a.获取SD卡的目录
    File sdCardDir=Environment.getExternalStorageDirectory();	 //获取SD卡的目录
    File targetFile=new File(sdCardDir.getCanonicalPath()+FILE_NAME);	//在指定路径下实例化一个File对象
    //b.以指定文件创建RandomAccessFile对象,向SD卡指定文件追加内容(targetFile为一个文件对象)
    RandomAccessFile raf=new RandomAccessFile(targetFile,"rw");
    //c.将文件记录指针移动到最后
    raf.seek(targetFile.length());
    //d.输出文件内容并关闭RandomAccessFile
    raf.write(content.getBytes());
    raf.close();
   }
   else
   {
    Toast.makeText(this, "手机没有插入SD卡,请插入SD卡再试试", Toast.LENGTH_SHORT).show();
   }
  }catch(IOException e){
   e.printStackTrace();
  }
 
 }
 //3.成员函数:读SD卡,如果手机插入了SD卡,而且应用程序具有访问SD的权限
 private String read()  {
  try{
   if(Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED))
   {
    //a.获取SD卡的目录
    File sdCardDir=Environment.getExternalStorageDirectory();
    //b.获取指定文件对应的输入流
    FileInputStream fis=new FileInputStream(sdCardDir.getCanonicalPath()+FILE_NAME);
    //c.将指定输入流包装成BufferedReader
    BufferedReader br=new BufferedReader(new InputStreamReader(fis));
    StringBuilder sb=new StringBuilder("");
   
    //c.循环读取文件内容
    String line=null;
    while((line=br.readLine())!=null)
    {
     sb.append(line);
    }
    //d.关闭资源并返回读取到的内容
    br.close();
    return sb.toString();
   }
   else
   {
    Toast.makeText(this, "手机没有插入SD卡,请插入SD卡再试试", Toast.LENGTH_SHORT).show();
   }
  }
  catch(Exception e)
  {
   e.printStackTrace();
  }
  return null;
 }
}
注释1:RandomAccessFile向SD卡指定文件追加内容--如果使用FIleOutputStream向指定文件写入数据,FileOutputStream会把原有的文件内容清空,那就不是追加文件内容了。
效果演示:

二、实战:SD卡文件浏览器
实现功能:当程序启动时,系统启动获取/mnt/sdcard目录下的全部文件。文件夹,并使用ListView将它们显示出来;当用户单击ListView指定的列表项时,系统将会显示该列表项下全部文件夹和内容。
1.界面布局文件\res\layout\main.xml
<?xml version="1.0" encoding="utf-8" ?> 
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" 
android:layout_width="match_parent" 
android:layout_height="match_parent" > 
<!-- 显示当前路径的文本框 --> 
<TextView 
android:id="@+id/path" 
android:layout_width="fill_parent" 
android:layout_height="wrap_content" 
android:layout_gravity="center_horizontal" 
android:layout_alignParentTop="true" /> 
<!-- 列表当前路径下所有文件的ListView --> 
<ListView 
android:id="@+id/list" 
android:layout_width="wrap_content" 
android:layout_height="wrap_content" 
android:divider="#000" 
android:dividerHeight="1px" 
android:layout_below="@id/path"/> 
<!-- 返回上一级目录的按钮 --> 
<Button 
android:id="@+id/parent" 
android:layout_width="50dp" 
android:layout_height="34dp" 
android:background="@drawable/home" 
android:layout_centerHorizontal="true" 
android:layout_alignParentBottom="true"/> 
</RelativeLayout>
2.主程序\src\包名\SDFileExplorer.java:利用File的ListFile列出指定目录的全部文件
package com.example.android_sdcard_1;
/*SD卡文件浏览器*/
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.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;
//应用出现NullPointerException
public class MianActivity extends Activity {
 ListView listView=null;
 TextView textView=null;
 File currentParent=null;	 //记录当前的父文件夹
 File[] currentFiles;	//记录当前路径下的所有文件的文件数组
 
 /*1.onCreate成员函数*/
 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.mian);
  listView=(ListView)findViewById(R.id.list);//获取列出全部文件的ListView
  textView=(TextView)findViewById(R.id.path);
  //a.获取系统的SD卡的目录
  File root=new File("/mnt/sdcard");
  //b.判断SD卡是否存在,如果存在获取指定文件夹下的所有文件并填充到ListView中
  if(root.exists())
  {
   currentParent=root;	 //记录当前的父文件夹为/mnt/sdcard
   currentFiles=root.listFiles();	//将当/mnt/sdcard路径下的所有文件存放到数组currentFiles中
   inflateListView(currentFiles);  //使用当前目录下的全部文件、文件夹来填充listView组件中
 
  //c.为ListView的列表项的单击事件绑定监听器
   listView.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();	//列出子文件夹下的所有文件或目录并保存到tmp数组中
     if(tmp==null || tmp.length == 0)
     {
      Toast.makeText(MianActivity.this, "提示信息:当前路径不可访问或者该路径下没有文件", Toast.LENGTH_SHORT).show();
     }
     else
     {
      //1.获取用户单击的列表项对应的文件夹,设为当前的父文件夹
      currentParent=currentFiles[position];
      //2.保存当前的父文件夹内的全部文件和文件夹
      currentFiles=tmp;
      //3.再次更新listView中的数据
      inflateListView(currentFiles);
     }
    }
   
   });
   
  //d.获取上一级目录的按钮,并为按钮设置监听器
   Button parent=(Button)findViewById(R.id.parent);
   parent.setOnClickListener(new OnClickListener(){
    @Override
    public void onClick(View v) {
     try{
      if(!currentParent.getCanonicalFile().equals("/mnt/sdcard"))
      {
       //1.获取上一级目录
       currentParent=currentParent.getParentFile();
       //2.列出当前目录下所有文件
       currentFiles=currentParent.listFiles();
       //3.再次更新ListView
       inflateListView(currentFiles);
      }
     }
     catch(IOException e)
     {
      e.printStackTrace();
     }
    }
   
   });
   
  }
 }
 
 /*2.inflateListView成员函数-更新列表组件内容*/
 private void inflateListView(File[] files) {
  //a.创建一个List集合,List集合的元素是Map
  List<Map<String,Object>> listItems=new ArrayList<Map<String,Object>>();
  //b.依次将文件夹下所有的文件或文件夹名称存放到List集合中
  for(int i=1;i<files.length;i++)
  {
   Map<String,Object> listItem=new HashMap<String,Object>();	//创建一个Map实例,所有数据使用哈希表组织排序
   if(files[i].isDirectory())	 //如果当前File是文件夹,使用folder图标;否者使用file图标
   {
    listItem.put("icon", R.drawable.folders);
   }
   else
   {
    listItem.put("icon", R.drawable.file);
   }
   listItem.put("filename", files[i].getName());	//将返回的文件名映射到filename键中
   listItems.add(listItem);	 //将一个列表项添加到List集合中
  }
  //c.创建一个SimpleAdapter,实现数据到listview组件的映射
  SimpleAdapter simpleAdapter=new SimpleAdapter(this
    ,listItems
    ,R.layout.line
    ,new String[]{"icon", "fileName"}
    ,new int[]{R.id.icon,R.id.file_name});
  //d.为ListView设置Adapter
  listView.setAdapter(simpleAdapter);
  try{
   textView.setText("当前路径为:"+currentParent.getCanonicalPath());
  }catch(IOException e)
  {
   e.printStackTrace();
  }
 }
}

3.列表视图资源文件\res\layout\line.xml
<?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/file_name" 
android:layout_width="match_parent" 
android:layout_height="wrap_content" 
android:textColor="#000000"/>" 
</LinearLayout>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值