Android 数据存储(二)——File与IO
【File 与 IO 存储】
1、Android的数据存储基本上没有什么更新的内容,我们可以将Java中的那一套File和Io体系拿过来直接使用,仅仅有一些边缘性的东西要介绍一下,所以这部分内容,首先将新的内容讲解一下,主要部分放在实例上面,通过实例,我们能够快速地掌握这部分知识
2、我们知道在手机中存储器一般分为两部分:手机内置的存储区(相对较小),可插拔的SD卡存储区(可扩展相对较大),但是现在有的手机比如小米3,它不支持可插拔的SD卡,也就是说,小米3 将SD直接焊接在内部了,不能够认为的更换,但是小米3的16G存储区中,依然分为:内置存储目录即/data/data/和SD卡存储目录;
3、一般来说我们的手机上的安装的每个应用的数据都分为两大类,一些数据存放在/data/data/<Package name>/files目录下,这些数据一般是比较重要的初始化数据等,我们称之为数据文件夹;另外一部分数据存放在SD卡目录下即/mnt/sdcard/目录下,这部分数据一般是应用程序存储的一些外部数据,比如文件、图片等等,我们称之为SD卡文件夹
4、好了,上面的问题搞清楚之后,就继续往下看:
(1)Java中的那一套File和IO,在Android中一般是用在SD卡的读取和存储上,这和Java中一模一样,不用做其他的解释
(2)对于内置内存的读取,即应用程序的数据文件夹来说,一般使用Android提供的openFileOutput()和 openFileInputStream()方法来获得指定文件的FileInputStream 和 FileOutputStream流 ,得到这些流对象之后就能够使用Java中那一套了
Context提供了如下两个方法来打开本应用程序的数据文件夹里的文件的IO流
FileInputStream openFileInputStream(String name):
打开应用程序的数据文件夹下的name文件对应的输入流(/data/data/<Package name>/files/name )
FileOutputStream openFileOutputStream(String name , int mode) :
打开应用程序的数据文件夹下的name文件对应的输入流(/data/data/<Package name>/files/name )
使用这两个方法,相当于将/data/data/<Package name>/files/目录变成了默认目录,我们只要在方法中的参数中指定文件的名字就行了,不用指定完全路径就能够访问应用程序的数据文件夹
其中的mode参数,指定的是文件的打开方式,还是Context中的静态常量:
Context.MODE_PRIVATE : 该文件只能够被当前的应用程序读写
Context.MODE_APPEND:已追加的方式打开文件
Context.MODE_WORLD_READBLE:该应用程序中的数据能够被其他的程序读
Context.MODE_WORLD_WRITEABLE:该应用程序中的数据能够被其他的程序读、写
(3)除此之外、Context还提供了如下几个方法来访问应用程序的数据文件夹
getDir(String name , int mode): 在应用程序的数据文件夹下获取或者创建name对应的子目录
File getFilesDir(): 获取应用程序的数据文件夹的绝对路径
String [ ] fileList():返回该应用程序的数据文件下的全部文件
deleteFile(String ):删除该应用程序的数据文件下的指定文件
5、好了现在将Android中新增的内容全部介绍完了,接下来看介个应用程序实例:
【实例应用】
【实例一:数据文件夹下的读写】

主Activity文件
1 public class MainActivity extends Activity { 2 3 4 static final String FILE_NAME = "FileDataStore.bin"; 5 6 Button toFileButton ; 7 Button fromFileButton ; 8 9 EditText toFileText ; 10 EditText fromFileText ; 11 12 @Override 13 protected void onCreate(Bundle savedInstanceState) { 14 super.onCreate(savedInstanceState); 15 setContentView(R.layout.activity_main); 16 17 toFileButton = (Button)findViewById(R.id.toFileButton); 18 fromFileButton = (Button)findViewById(R.id.fromFileButton); 19 toFileText = (EditText)findViewById(R.id.toFileText); 20 fromFileText = (EditText)findViewById(R.id.fromFileText); 21 22 toFileButton.setOnClickListener(new OnClickListener(){ 23 24 @Override 25 public void onClick(View v) { 26 writeToFile(toFileText.getText().toString()); 27 toFileText.setText(""); 28 } 29 }); 30 31 fromFileButton.setOnClickListener(new OnClickListener(){ 32 33 @Override 34 public void onClick(View v) { 35 fromFileText.setText(readFromFile()); 36 } 37 }); 38 39 } 40 41 42 public void writeToFile(String content) { 43 FileOutputStream fos; 44 try { 45 46 fos = openFileOutput(FILE_NAME,MODE_APPEND); 47 BufferedWriter bf = new BufferedWriter(new OutputStreamWriter(fos)); 48 bf.write(content); 49 bf.flush(); 50 51 } catch (FileNotFoundException e) { 52 e.printStackTrace(); 53 }catch(IOException e){ 54 e.printStackTrace(); 55 } 56 } 57 58 59 public String readFromFile() { 60 FileInputStream fis; 61 try { 62 char [ ] bufferChars = new char [1024] ; 63 StringBuilder tempBuffer = new StringBuilder(""); 64 fis = openFileInput(FILE_NAME); 65 BufferedReader bf = new BufferedReader(new InputStreamReader(fis)); 66 while(bf.read(bufferChars) > 0){ 67 tempBuffer.append(bufferChars); 68 } 69 fis.close(); 70 return tempBuffer.toString(); 71 } catch (FileNotFoundException e) { 72 e.printStackTrace(); 73 }catch(IOException e){ 74 e.printStackTrace(); 75 } 76 return null ; 77 } 78 }
【实例二:SD卡文件夹下的读写】
首先我们先来介绍一下SD下的文件数据的读写操作
1、当程序通过Context的openFileInput或openFileOutput方法来打开文件的输入流和输出流的时候,程序打开的是应用程序的数据文件夹里的文件,这样存储的文件大小是有限的,因为一般来说,内置存储区相对较小,所以为了存储一些大数据文件,一般选择在SD下进行存储
2、读写SD卡上的文件一般按如下步骤进行:
(1)调用Environment的getExternalStorageState()方法判断手机上面是否插入了SD卡,并且应用程序是否有读写SD卡的权限,使用如下代码:
Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)
如果符合上述条件的话,就会返回true
(2)调用Environment的getExternalStorageDirector()方法来获得SD卡的目录,也就是 /mnt/sdcard/ , 当然如果你完全可以使用 “/mnt/sdcard/”直接创建文件File对象
(3)之后就是用Java中的那一套流对象来进行文件数据的读取与写入
(4)为了让本应用程序有对SD卡的访问和读写权限,需要在Manifest.xml文件中赋予相关权限:
<!-- 在SD卡中创建和删除文件的权限 --> <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/> <!-- 向SD卡中写入数据的权限 --> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
5、了解了上面的内容我们就能够对SD卡文件进行数据的读写了,下面的程序界面和上面的程序一样,只是文件的位置在SD卡中
主Activity文件:
1 import java.io.BufferedReader; 2 import java.io.File; 3 import java.io.FileInputStream; 4 import java.io.IOException; 5 import java.io.InputStreamReader; 6 import java.io.RandomAccessFile; 7 8 import android.app.Activity; 9 import android.os.Bundle; 10 import android.os.Environment; 11 import android.view.Menu; 12 import android.view.MenuItem; 13 import android.view.View; 14 import android.view.View.OnClickListener; 15 import android.widget.Button; 16 import android.widget.EditText; 17 18 public class MainActivity extends Activity { 19 20 21 static final String FILE_NAME = "/FileDataStore.txt"; 22 23 Button toFileButton ; 24 Button fromFileButton ; 25 26 EditText toFileText ; 27 EditText fromFileText ; 28 29 @Override 30 protected void onCreate(Bundle savedInstanceState) { 31 super.onCreate(savedInstanceState); 32 setContentView(R.layout.activity_main); 33 34 toFileButton = (Button)findViewById(R.id.toFileButton); 35 fromFileButton = (Button)findViewById(R.id.fromFileButton); 36 toFileText = (EditText)findViewById(R.id.toFileText); 37 fromFileText = (EditText)findViewById(R.id.fromFileText); 38 39 toFileButton.setOnClickListener(new OnClickListener(){ 40 41 @Override 42 public void onClick(View v) { 43 writeToFile(toFileText.getText().toString()); 44 toFileText.setText(""); 45 } 46 }); 47 48 fromFileButton.setOnClickListener(new OnClickListener(){ 49 50 @Override 51 public void onClick(View v) { 52 fromFileText.setText(readFromFile()); 53 } 54 }); 55 56 } 57 58 59 public void writeToFile(String content) { 60 try { 61 //判定手机中是否插入了SD卡,并且本应用程序有读取权限 62 if(Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)){ 63 //获取SD卡的目录 64 File sdCardDir = Environment.getExternalStorageDirectory() ; 65 File targetFile; 66 67 targetFile = new File(sdCardDir.getCanonicalFile()+FILE_NAME); 68 69 //已指定的文件创建RandomAccessFile对象 70 RandomAccessFile raf = new RandomAccessFile(targetFile , "rw"); 71 //将文件当前指针移动到内容的末尾 72 raf.seek(targetFile.length()); 73 //将内容写到文件中 74 raf.write(content.getBytes()); 75 raf.close(); 76 } 77 } catch (IOException e) { 78 e.printStackTrace(); 79 } 80 } 81 82 83 84 public String readFromFile() { 85 try{ 86 //判定手机中是否插入了SD卡,并且本应用程序有读取权限 87 if(Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)){ 88 File sdCardDir = Environment.getExternalStorageDirectory() ; 89 FileInputStream fis = new FileInputStream(sdCardDir.getCanonicalPath()+FILE_NAME); 90 BufferedReader br = new BufferedReader(new InputStreamReader(fis)); 91 StringBuilder contentBuffered = new StringBuilder(""); 92 String tempLines = ""; 93 while((tempLines = br.readLine()) != null){ 94 contentBuffered.append(tempLines); 95 } 96 br.close(); 97 return contentBuffered.toString(); 98 } 99 }catch(IOException e){ 100 e.printStackTrace(); 101 } 102 return null ; 103 } 104 }
最后记得在Manifest.xml文件中赋予相关权限
【实例三:SD卡文件浏览器】
效果如下:(文件夹和文件的图标不一样,最上面的路径如果占不下的话会有省略号,当我们点击下面的“返回”按钮时,文件目录就会返回到上一级)

主布局文件activity_main.xml
1 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" 2 xmlns:tools="http://schemas.android.com/tools" 3 android:layout_width="match_parent" 4 android:layout_height="match_parent" 5 tools:context="com.penglee.sdfilesexplorer.MainActivity" > 6 7 <TextView 8 android:id="@+id/filesPath" 9 android:layout_width="match_parent" 10 android:layout_height="wrap_content" 11 android:textColor="#FF999999" 12 android:paddingTop="10dp" 13 android:ellipsize="middle" 14 android:singleLine="true"/> 15 16 <ListView 17 android:id="@+id/filesList" 18 android:layout_width="match_parent" 19 android:layout_height="wrap_content" 20 android:layout_below="@id/filesPath" 21 android:paddingTop="10dp" 22 android:paddingBottom="50dp"> 23 </ListView> 24 25 <Button 26 android:id="@+id/home" 27 android:layout_width="40dp" 28 android:layout_height="40dp" 29 android:background="@drawable/home" 30 android:layout_alignParentBottom="true" 31 android:layout_centerHorizontal="true"/> 32 </RelativeLayout>
主Activity文件MainActivity.java 文件
1 package com.penglee.sdfilesexplorer; 2 3 import java.io.File; 4 import java.io.IOException; 5 import java.util.ArrayList; 6 import java.util.HashMap; 7 import java.util.List; 8 import java.util.Map; 9 10 import android.app.Activity; 11 import android.os.Bundle; 12 import android.view.View; 13 import android.view.View.OnClickListener; 14 import android.widget.AdapterView; 15 import android.widget.AdapterView.OnItemClickListener; 16 import android.widget.Button; 17 import android.widget.ListView; 18 import android.widget.SimpleAdapter; 19 import android.widget.TextView; 20 import android.widget.Toast; 21 22 public class MainActivity extends Activity { 23 24 Button home ; //返回上一级的按钮 25 ListView filesList ; //显示文件的ListView 26 TextView filesPath ; // 最上面的显示文件路径的TextView 27 28 File currentParent = null ; //当前ListView显示的文件的父文件夹 29 File[ ] currentFiles = null ; //当前ListView应该显示的文件集合 30 31 @Override 32 protected void onCreate(Bundle savedInstanceState) { 33 super.onCreate(savedInstanceState); 34 setContentView(R.layout.activity_main); 35 36 home = (Button)findViewById(R.id.home); 37 filesList = (ListView)findViewById(R.id.filesList); 38 filesPath = (TextView)findViewById(R.id.filesPath); 39 40 File root = new File("/mnt/sdcard/") ; 41 //如果sdcard目录存在 42 if(root.exists()){ 43 currentParent = root ; 44 currentFiles = root.listFiles(); 45 } 46 47 //更新当前的ListView视图 48 upDateListView(currentFiles) ; 49 50 //为ListView注册监听器 51 filesList.setOnItemClickListener(new OnItemClickListener(){ 52 53 @Override 54 public void onItemClick(AdapterView<?> parent, View view, 55 int position, long id) { 56 57 //假如单击的Item对应的文件为不是文件夹,就直接返回 58 if(currentFiles[position].isFile()) return ; 59 60 //如果单击的选项对应的是一个文件夹 61 File [ ] temp = currentFiles[position].listFiles(); 62 if(temp == null){ 63 Toast.makeText(MainActivity.this, "当前文件夹下的文件不可访问", Toast.LENGTH_SHORT) 64 .show(); 65 } 66 else{ 67 currentParent = currentFiles[position]; 68 currentFiles = temp; 69 upDateListView(currentFiles) ; 70 } 71 } 72 }); 73 74 //为返回上一级的按钮添加事件监听 75 home.setOnClickListener(new OnClickListener(){ 76 77 @Override 78 public void onClick(View v) { 79 80 try { 81 if(! currentParent.getCanonicalPath().equals("/mnt")){ 82 83 currentParent = currentParent.getParentFile() ; 84 currentFiles = currentParent.listFiles(); 85 upDateListView(currentFiles) ; 86 } 87 } catch (IOException e) { 88 e.printStackTrace(); 89 } 90 } 91 }); 92 } 93 94 private void upDateListView(File [ ] files ){ 95 96 //创建一个存储数据的List集合 97 List<Map<String , Object>> listItems = new ArrayList<Map<String , Object>>( ) ; 98 99 for(int i =0 ; i<files.length ; i++){ 100 Map<String , Object> listItem = new HashMap<String , Object>() ; 101 102 //根据文件和文件夹的不同,加载不同的图标 103 if(files[i].isFile()) 104 listItem.put("icon", R.drawable.file); 105 else 106 listItem.put("icon", R.drawable.folder); 107 108 listItem.put("filename", files[i].getName()); 109 110 listItems.add(listItem); 111 } 112 113 //创建一个SimpleAdapter 114 SimpleAdapter simpleAdapter = new SimpleAdapter(MainActivity.this 115 , listItems , R.layout.item 116 ,new String[ ]{"icon","filename"} 117 ,new int [ ]{R.id.icon , R.id.filename}); 118 filesList.setAdapter(simpleAdapter); 119 120 //更新当前的文件的路径 121 try { 122 filesPath.setText("当前路径为:"+currentParent.getCanonicalPath()); 123 } catch (IOException e) { 124 e.printStackTrace(); 125 } 126 } 127 }
item.xml文件
1 <?xml version="1.0" encoding="utf-8"?> 2 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 3 android:layout_width="match_parent" 4 android:layout_height="wrap_content" 5 android:orientation="horizontal" > 6 7 <ImageView 8 android:id="@+id/icon" 9 android:layout_width="40dp" 10 android:layout_height="40dp" 11 android:padding="10dp"/> 12 13 <TextView 14 android:id="@+id/filename" 15 android:layout_width="match_parent" 16 android:layout_height="wrap_content" 17 android:gravity="center_vertical" 18 android:textSize="16dp" 19 android:padding="10dp"/> 20 21 </LinearLayout>
最后要在Manifest.xml为文件中添加权限
<!-- 有读取SD文件的权限 --> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
【分析】当我们一直点击返回按钮,就会回到/mnt/目录下,我们来看看这个目录下都有哪些文件:

这个目录下后面四个文件我们是没有访问权限的,至于这些文件是干什么的,以后再介绍

浙公网安备 33010602011771号