【Android开发日记】之入门篇(七)——Android数据存储(上)
一、Android的文件系统
- Android系统文件目录
目录 内容 system 系统目录,放置在Android运行所需的核心库 data 应用目录,放置着运行在Android上的应用及其数据 sdcard 扩展存储卡目录,用来存放共享的数据 mnt 记录Android挂载的外部存储信息 - Android的应用数据存储机制
在Android中,第三方应用及其数据,都存放在data目录下。其中,应用安装包会被存放到/data/app/目录下,每个安装包的文件名都形如:应用包名.apk,以避免重复。
比如包名为com.test.sample的应用,其应用数据的目录为/data/data/com.test.sample/。对应的数据库文件存储在/data/data/com.test.sample/database/目录下,设置文件存储在/data/data/com.test.sample/shared_prefs/,自定义的应用数据文件存储在目录/data/data/com.test.sample/files/下,等等。
不仅如此,Android还会为每个应用创建一个账号,只有通过本应用的账号才有权限去运行该应用的安装包文件,读写应用数据目录下的文件(当然root权限除外啊~),从而保证了该应用数据不会再被其他应用获取或破坏。 - Android的文件操作
从应用数据目录下可以看出,数据文件可以分成两类,一类是放置在扩展存储器中的文件,即/sdcard/目录下的文件,它们可以被各个应用共享;而另一类则是放在该应用数据目录下文件,它们仅能被各个应用独享,不能被其他应用读写。
(1)扩展存储器中的文件读写方式跟标准的java文件处理无异。
我们可以新建一个FileUtil的工具类来帮助我们处理文件的I/O操作,首先我们先判断SD卡的状态,看看SD卡是否可用,还有多少可用容量等。新建一个FileUtil的Class,加入方法
1 // =================get SDCard information=================== 2 public static boolean isSdcardAvailable() { 3 String status = Environment.getExternalStorageState(); 4 //Environment.MEDIA_MOUNTED表示SD卡正常挂载 5 if (status.equals(Environment.MEDIA_MOUNTED)) { 6 return true; 7 } 8 return false; 9 } 10 11 public static long getSDAllSizeKB() { 12 //sd卡的位置 13 File path = Environment.getExternalStorageDirectory(); 14 //StatFs获取的都是以block为单位的 15 StatFs sf = new StatFs(path.getPath()); 16 // 得到单个block的大小 17 long blockSize = sf.getBlockSize(); 18 // 获取所有数据块数 19 long allBlocks = sf.getBlockCount(); 20 // 返回SD卡大小 21 return (allBlocks * blockSize) / 1024; // KB 22 } 23 24 /** 25 * free size for normal application 26 * @return 27 */ 28 public static long getSDAvalibleSizeKB() { 29 File path = Environment.getExternalStorageDirectory(); 30 StatFs sf = new StatFs(path.getPath()); 31 long blockSize = sf.getBlockSize(); 32 long avaliableSize = sf.getAvailableBlocks(); 33 return (avaliableSize * blockSize) / 1024;// KB 34 }
Environment.getExternalStorageDirectory()表示获取扩展存储器的目录。(建议使用此方法动态获取,因为sdcard这个目录路径是可配置的)
StatFs.getBlockSize在API18后变为StatFs.getBlockSizeLong,其他类似的getBlock方法也一样,关于StatFs,详情可以看这篇博文
然后在activity中的button1加入事件case R.id.button1: { Log.d("TEST", "sdcard?"+FileUtil.isSdcardAvailable()); Log.d("TEST", "全部容量"+(float)FileUtil.getSDAllSizeKB()/1024/1024); Log.d("TEST", "可用容量"+(float)FileUtil.getSDAvalibleSizeKB()/1024/1024); Toast.makeText(this, "status", Toast.LENGTH_SHORT).show(); break; }
运行结果如下
接下来我们来判断某个文件夹是否存在在SD卡中以及创建一个文件夹
/** * @param director 文件夹名称 * @return */ public static boolean isFileExist(String director) { File file = new File(Environment.getExternalStorageDirectory() + File.separator + director); return file.exists(); } /** * create multiple director * @param path * @return */ public static boolean createFile(String director) { if (isFileExist(director)) { return true; } else { File file = new File(Environment.getExternalStorageDirectory() + File.separator + director); if (!file.mkdirs()) { return false; } return true; } }
其中File.separator是表示分隔符,在不同操作系统下是不同的,如windows就是代表"/",而在Linux下却是代表"\"。所以介意使用File.separator来代替分隔符。File.mkdirs()表示创建一个文件夹,且可附带创建父目录,而mkdir()不行,详情的File大家可以查看官方文档,或者看看这篇博文
然后在activity中的button2加入响应事件case R.id.button2: { Log.d("TEST", "example文件夹存在?"+FileUtil.isFileExist("example")); Log.d("TEST", "创建forexample文件夹"+FileUtil.createFile("forexample")); Toast.makeText(this, "IsFile", Toast.LENGTH_SHORT).show(); break; }
运行后可以看到
我们会发现在手机的sdcard目录下新建了一个forexample的文件夹。
最后我们来实现文件的读和写
写:/** * * @param director * (you don't need to begin with * Environment.getExternalStorageDirectory()+File.separator) * @param fileName * @param content * @param encoding * (UTF-8...) * @param isAppend * : Context.MODE_APPEND * @return */ public static File writeToSDCardFile(String directory, String fileName, String content, String encoding, boolean isAppend) { // mobile SD card path +path File file = null; OutputStream os = null; try { if (!createFile(directory)) { return file; } file = new File(Environment.getExternalStorageDirectory() + File.separator + directory + File.separator + fileName); os = new FileOutputStream(file, isAppend); if (encoding.equals("")) { os.write(content.getBytes()); } else { os.write(content.getBytes(encoding)); } os.flush(); } catch (IOException e) { Log.e("FileUtil", "writeToSDCardFile:" + e.getMessage()); } finally { try { if (os != null) { os.close(); } } catch (IOException e) { e.printStackTrace(); } } return file; } /** * write data from inputstream to SDCard */ public File writeToSDCardFromInput(String directory, String fileName, InputStream input) { File file = null; OutputStream os = null; try { if (createFile(directory)) { return file; } file = new File(Environment.getExternalStorageDirectory() + File.separator + directory + File.separator + fileName); os = new FileOutputStream(file); byte[] data = new byte[bufferd]; int length = -1; while ((length = input.read(data)) != -1) { os.write(data, 0, length); } // clear cache os.flush(); } catch (Exception e) { Log.e("FileUtil", "" + e.getMessage()); e.printStackTrace(); } finally { try { os.close(); } catch (Exception e) { e.printStackTrace(); } } return file; }
从上面可以看到有两种写入的方法,一种是将字符串直接写入,另一种是将数据流写到文件中。还有一点要提的是file的默认目录就是sdcard的目录,所以开头不必每次都要加sdcard的目录路径。
FileOutputStream(file, isAppend) 两个参数,左边是File文件,而右边是一个boolean值,为true时,数据将会接在原来文件的后面写入,而false是则会覆盖。
读:public static String ReadFromSDCardFile(String directory,String fileName){ String res=""; File file = null; file = new File(Environment.getExternalStorageDirectory() + File.separator + directory + File.separator + fileName); try { FileInputStream fis = new FileInputStream(file); int length = fis.available(); byte [] buffer = new byte[length]; fis.read(buffer);
//将字节按照编码格式转成字符串 res = EncodingUtils.getString(buffer, "UTF-8"); fis.close(); return res; }catch (FileNotFoundException e) { // TODO Auto-generated catch block Log.d("TEST", "FileNotFound"); e.printStackTrace(); }catch (Exception e) { Log.d("TEST", "Can Not Open File"); e.printStackTrace(); } return null; }编码默认是UTF-8,若是想要改变的话,将其作为参数传入就行。
Activity中在按钮中加入响应case R.id.button3: { FileUtil.writeToSDCardFile("forexample", "test.txt", editText.getText().toString(), "UTF-8", true); Toast.makeText(this, "WriteFile", Toast.LENGTH_SHORT).show(); break; } case R.id.button4: { textView.setText(FileUtil.ReadFromSDCardFile("forexample", "test.txt")); Toast.makeText(this, "ReadFile", Toast.LENGTH_SHORT).show(); break; }
在文字编辑框上写入“我是cpacm”,先点击writefile按钮,再点击ReadFile,得到运行结果
同时在根目录下的forexample文件夹里会找到test.txt,里面有着“我是cpacm”的一行字。到此,文件的读写成功。
(2)放在该应用数据目录下的文件读写
存储在应用目录下的私有数据目录,通常不会通过File类的方式直接读写,而是利用一些封装过的类或函数来操作。一般可以通过Context.openFileOutput来执行。
在Activity加入两个方法,分别为文件的读和写public void writeFile(String fileName,String writestr){ try{ FileOutputStream fout =openFileOutput(fileName,MODE_PRIVATE); byte [] bytes = writestr.getBytes(); fout.write(bytes); fout.close(); } catch(Exception e){ e.printStackTrace(); } } //读数据 public String readFile(String fileName){ String res=""; try{ FileInputStream fin = openFileInput(fileName); int length = fin.available(); byte [] buffer = new byte[length]; fin.read(buffer); res = EncodingUtils.getString(buffer, "UTF-8"); fin.close(); } catch(Exception e){ e.printStackTrace(); } return res; }
同时在按钮的响应中加入
case R.id.button5: { writeFile("test2.txt",editText.getText().toString()); Toast.makeText(this, "WritePrivateFile", Toast.LENGTH_SHORT).show(); break; } case R.id.button6: { textView.setText(readFile("test2.txt")); Toast.makeText(this, "ReadPrivateFile", Toast.LENGTH_SHORT).show(); break; }
效果图跟上张一样。
最后不要忘记在配置文件中声明权限
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />
二、Android设置文件的使用
用户在使用应用时,常常会有一些个人偏好。为了满足不同用户的需求,应用通常会提供对应的设置项(Preference),让用户根据自己的喜好选择。这些设置信息会存储在本地并进行结构化地展示,使用户可以编辑。
- 设置文件的存储和使用
Android应用的设置数据,可以通过android.content.SharedPreferences类来表示。它提供了一组数据读取的接口,可以从设置文件中读取给定键值的整形数,布尔型数等数据。
首先是获取SharedPreferences
private SharedPreferences userInfo;
//在界面组件或服务组件中调用,构造应用默认的设置文件,默认文件名字为_preferences.xml //userInfo = PreferenceManager.getDefaultSharedPreferences(this); //或获取指定名字的SharedPreferences对象 参数分别为存储的文件名和存储模式。 userInfo = getSharedPreferences("preferences", Activity.MODE_PRIVATE); //读取数据,如果无法找到则会使用默认值 String username = userInfo.getString("name", "未定义姓名"); String msg = userInfo.getString("msg", "未定义信息"); //显示文本 textView.setText(username+","+msg);
两种获取方式,默认或者指定一个文件
接下来加入响应按钮case R.id.button7: { //获得SharedPreferences的编辑器 SharedPreferences.Editor editor = userInfo.edit(); //将信息存入相应的键值中 editor.putString("name", editText.getText().toString()).commit(); Toast.makeText(this, "SetName", Toast.LENGTH_SHORT).show(); break; } case R.id.button8: { //获得SharedPreferences的编辑器 SharedPreferences.Editor editor = userInfo.edit(); //将信息存入相应的键值中ss editor.putString("msg", editText.getText().toString()).commit(); Toast.makeText(this, "SetMessage", Toast.LENGTH_SHORT).show(); break; } case R.id.button9: {
//获得SharedPreferences文件 userInfo = getSharedPreferences("preferences", Activity.MODE_PRIVATE); String username = userInfo.getString("name", "未定义姓名"); String msg = userInfo.getString("msg", "未定义信息"); textView.setText(username+","+msg); Toast.makeText(this, "ShowMsg", Toast.LENGTH_SHORT).show(); break; } case R.id.button10: {
//输出XML文件 textView.setText(print()); Toast.makeText(this, "ShowXML", Toast.LENGTH_SHORT).show(); break; }按钮7,8可以设置信息,按钮9则从SharedPreferences文件中读取信息并显示在文字框中。按钮10会显示这个XML文件中的所有信息。
访问其他应用中的Preference(在SecondApp中访问FirstApp的数据),前提条件是:FirstApp的preference创建时指定了Context.MODE_WORLD_READABLE或者Context.MODE_WORLD_WRITEABLE权限。如:在<package name>为com.first.app的应用使用下面语句创建了preference("first_app_perferences")。
Java代码在SecondApp中要访问FirstApp应用中的preference,首先需要创建FirstApp应用的Context,然后通过Context 访问preference ,访问preference时会在应用所在包下的shared_prefs目录找到preference
Context firstAppContext = createPackageContext("com.first.app", Context.CONTEXT_IGNORE_SECURITY); SharedPreferences sharedPreferences = firstAppContext.getSharedPreferences("first_app_perferences", Context.MODE_WORLD_READABLE); String name = sharedPreferences.getString("name", ""); int age = sharedPreferences.getInt("age", 0);
如果不通过创建Context访问FirstApp应用的preference,可以以读取xml文件方式直接访问FirstApp应用的preference对应的xml文件,
如:
File xmlFile = new File(“/data/data/<package name>/shared_prefs/first_app_perferences.xml”);//<package name>应替换成应用的包名: com.first.app - 设置界面组件
有一类特殊的Preference对象:android.preference.PreferenceGroup。它是容器型的Preference对象,负责管理一组相关联的Preference对象。设置项编辑的界面组件,通常派生自android.preference.PreferenceActivity类。它可以将一个定制好的设置树转换成对应的控件呈现出来。
public class PreferencesDemo extends PreferenceActivity{ @Override public void onCreate(Bundle savadInstanceState){ super.onCreate(savadInstanceState); this.addPreferencesFromResource(R.xml.preference); } }
其中,R.xml.preference表示描述设置信息的资源文件。放在XML资源目录下。
详细可以参考Android的配置界面PreferenceActivity
1 public class MainActivity extends Activity implements OnClickListener { 2 3 /** 存储后的文件路径:/data/data/<package name>/shares_prefs + 文件名.xml */ 4 public static final String PATH = "/data/data/com.example.datademo/shared_prefs/preferences.xml"; 5 private SharedPreferences userInfo; 6 7 private Button button1; 8 private Button button2; 9 private Button button3; 10 private Button button4; 11 private Button button5; 12 private Button button6; 13 private Button button7; 14 private Button button8; 15 private Button button9; 16 private Button button10; 17 private TextView textView; 18 private EditText editText; 19 20 @Override 21 protected void onCreate(Bundle savedInstanceState) { 22 super.onCreate(savedInstanceState); 23 setContentView(R.layout.activity_main); 24 25 // 获得界面的控件 26 textView = (TextView) findViewById(R.id.textView1); 27 editText = (EditText) findViewById(R.id.editText1); 28 button1 = (Button) findViewById(R.id.button1); 29 button1.setOnClickListener(this); 30 button2 = (Button) findViewById(R.id.button2); 31 button2.setOnClickListener(this); 32 button3 = (Button) findViewById(R.id.button3); 33 button3.setOnClickListener(this); 34 button4 = (Button) findViewById(R.id.button4); 35 button4.setOnClickListener(this); 36 button5 = (Button) findViewById(R.id.button5); 37 button5.setOnClickListener(this); 38 button6 = (Button) findViewById(R.id.button6); 39 button6.setOnClickListener(this); 40 button7 = (Button) findViewById(R.id.button7); 41 button7.setOnClickListener(this); 42 button8 = (Button) findViewById(R.id.button8); 43 button8.setOnClickListener(this); 44 button9 = (Button) findViewById(R.id.button9); 45 button9.setOnClickListener(this); 46 button10 = (Button) findViewById(R.id.button10); 47 button10.setOnClickListener(this); 48 49 //在界面组件或服务组件中调用,构造应用默认的设置文件,默认文件名字为_preferences.xml 50 //userInfo = PreferenceManager.getDefaultSharedPreferences(this); 51 //或获取指定名字的SharedPreferences对象 参数分别为存储的文件名和存储模式。 52 userInfo = getSharedPreferences("preferences.xml", Activity.MODE_PRIVATE); 53 54 //读取数据,如果无法找到则会使用默认值 55 String username = userInfo.getString("name", "未定义姓名"); 56 String msg = userInfo.getString("msg", "未定义信息"); 57 //显示文本 58 textView.setText(username+","+msg); 59 } 60 61 @Override 62 public void onClick(View v) { 63 // TODO Auto-generated method stub 64 switch (v.getId()) { 65 case R.id.button1: { 66 Log.d("TEST", "sdcard?"+FileUtil.isSdcardAvailable()); 67 Log.d("TEST", "全部容量"+(float)FileUtil.getSDAllSizeKB()/1024/1024); 68 Log.d("TEST", "可用容量"+(float)FileUtil.getSDAvalibleSizeKB()/1024/1024); 69 Toast.makeText(this, "status", Toast.LENGTH_SHORT).show(); 70 break; 71 } 72 case R.id.button2: { 73 Log.d("TEST", "example文件夹存在?"+FileUtil.isFileExist("example")); 74 Log.d("TEST", "创建forexample文件夹"+FileUtil.createFile("forexample")); 75 Toast.makeText(this, "IsFile", Toast.LENGTH_SHORT).show(); 76 break; 77 } 78 case R.id.button3: { 79 FileUtil.writeToSDCardFile("forexample", "test.txt", 80 editText.getText().toString(), "UTF-8", true); 81 Toast.makeText(this, "WriteFile", Toast.LENGTH_SHORT).show(); 82 break; 83 } 84 case R.id.button4: { 85 textView.setText(FileUtil.ReadFromSDCardFile("forexample", "test.txt")); 86 Toast.makeText(this, "ReadFile", Toast.LENGTH_SHORT).show(); 87 break; 88 } 89 case R.id.button5: { 90 writeFile("test2.txt",editText.getText().toString()); 91 Toast.makeText(this, "WritePrivateFile", Toast.LENGTH_SHORT).show(); 92 break; 93 } 94 case R.id.button6: { 95 textView.setText(readFile("test2.txt")); 96 Toast.makeText(this, "ReadPrivateFile", Toast.LENGTH_SHORT).show(); 97 break; 98 } 99 case R.id.button7: { 100 //获得SharedPreferences的编辑器 101 SharedPreferences.Editor editor = userInfo.edit(); 102 //将信息存入相应的键值中 103 editor.putString("name", editText.getText().toString()).commit(); 104 Toast.makeText(this, "SetName", Toast.LENGTH_SHORT).show(); 105 break; 106 } 107 case R.id.button8: { 108 //获得SharedPreferences的编辑器 109 SharedPreferences.Editor editor = userInfo.edit(); 110 //将信息存入相应的键值中ss 111 editor.putString("msg", editText.getText().toString()).commit(); 112 Toast.makeText(this, "SetMessage", Toast.LENGTH_SHORT).show(); 113 break; 114 } 115 case R.id.button9: { 116 userInfo = getSharedPreferences("preferences.xml", Activity.MODE_PRIVATE); 117 String username = userInfo.getString("name", "未定义姓名"); 118 String msg = userInfo.getString("msg", "未定义信息"); 119 textView.setText(username+","+msg); 120 Toast.makeText(this, "ShowMsg", Toast.LENGTH_SHORT).show(); 121 break; 122 } 123 case R.id.button10: { 124 textView.setText(print()); 125 Toast.makeText(this, "ShowXML", Toast.LENGTH_SHORT).show(); 126 break; 127 } 128 } 129 } 130 131 public void writeFile(String fileName,String writestr){ 132 try{ 133 FileOutputStream fout =openFileOutput(fileName,MODE_PRIVATE); 134 byte [] bytes = writestr.getBytes(); 135 fout.write(bytes); 136 fout.close(); 137 } 138 catch(Exception e){ 139 e.printStackTrace(); 140 } 141 } 142 143 //读数据 144 public String readFile(String fileName){ 145 String res=""; 146 try{ 147 FileInputStream fin = openFileInput(fileName); 148 int length = fin.available(); 149 byte [] buffer = new byte[length]; 150 fin.read(buffer); 151 res = EncodingUtils.getString(buffer, "UTF-8"); 152 fin.close(); 153 } 154 catch(Exception e){ 155 e.printStackTrace(); 156 } 157 return res; 158 } 159 160 private String print() { 161 StringBuffer buff = new StringBuffer(); 162 try { 163 BufferedReader reader = new BufferedReader(new InputStreamReader( 164 new FileInputStream(PATH))); 165 String str; 166 while ((str = reader.readLine()) != null) { 167 buff.append(str + "/n"); 168 } 169 } catch (Exception e) { 170 e.printStackTrace(); 171 } 172 return buff.toString(); 173 } 174 175 }
1 package com.example.datademo; 2 3 import java.io.File; 4 import java.io.FileInputStream; 5 import java.io.FileNotFoundException; 6 import java.io.FileOutputStream; 7 import java.io.IOException; 8 import java.io.InputStream; 9 import java.io.OutputStream; 10 11 import org.apache.http.util.EncodingUtils; 12 13 import android.os.Environment; 14 import android.os.StatFs; 15 import android.util.Log; 16 17 public class FileUtil { 18 private static int bufferd = 1024; 19 20 private FileUtil() { 21 } 22 23 /* 24 * <!-- 在SDCard中创建与删除文件权限 --> <uses-permission 25 * android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/> <!-- 26 * 往SDCard写入数据权限 --> <uses-permission 27 * android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> 28 */ 29 30 // =================get SDCard information=================== 31 public static boolean isSdcardAvailable() { 32 String status = Environment.getExternalStorageState(); 33 //Environment.MEDIA_MOUNTED表示SD卡正常挂载 34 //sd卡 http://blog.csdn.net/yuzhiboyi/article/details/8645730 35 if (status.equals(Environment.MEDIA_MOUNTED)) { 36 return true; 37 } 38 return false; 39 } 40 41 public static long getSDAllSizeKB() { 42 // get path of sdcard 43 File path = Environment.getExternalStorageDirectory(); 44 //StatFs获取的都是以block为单位的 http://blog.csdn.net/pang3510726681/article/details/6969557 45 StatFs sf = new StatFs(path.getPath()); 46 // get single block size(Byte) 47 long blockSize = sf.getBlockSize(); 48 // 获取所有数据块数 49 long allBlocks = sf.getBlockCount(); 50 // 返回SD卡大小 51 return (allBlocks * blockSize) / 1024; // KB 52 } 53 54 /** 55 * free size for normal application 56 * 57 * @return 58 */ 59 public static long getSDAvalibleSizeKB() { 60 File path = Environment.getExternalStorageDirectory(); 61 StatFs sf = new StatFs(path.getPath()); 62 long blockSize = sf.getBlockSize(); 63 long avaliableSize = sf.getAvailableBlocks(); 64 return (avaliableSize * blockSize) / 1024;// KB 65 } 66 67 // =====================File Operation========================== 68 /** 69 * @param director 文件夹名称 70 * @return 71 */ 72 public static boolean isFileExist(String director) { 73 File file = new File(Environment.getExternalStorageDirectory() 74 + File.separator + director); 75 return file.exists(); 76 } 77 78 /** 79 * create multiple director 80 * 81 * @param path 82 * @return 83 */ 84 public static boolean createFile(String director) { 85 if (isFileExist(director)) { 86 return true; 87 } else { 88 File file = new File(Environment.getExternalStorageDirectory() 89 + File.separator + director); 90 if (!file.mkdirs()) { 91 return false; 92 } 93 return true; 94 } 95 } 96 97 public static File writeToSDCardFile(String directory, String fileName, 98 String content, boolean isAppend) { 99 return writeToSDCardFile(directory, fileName, content, "", isAppend); 100 } 101 102 /** 103 * 104 * @param director 105 * (you don't need to begin with 106 * Environment.getExternalStorageDirectory()+File.separator) 107 * @param fileName 108 * @param content 109 * @param encoding 110 * (UTF-8...) 111 * @param isAppend 112 * : Context.MODE_APPEND 113 * @return 114 */ 115 public static File writeToSDCardFile(String directory, String fileName, 116 String content, String encoding, boolean isAppend) { 117 // mobile SD card path +path 118 File file = null; 119 OutputStream os = null; 120 try { 121 if (!createFile(directory)) { 122 return file; 123 } 124 file = new File(Environment.getExternalStorageDirectory() 125 + File.separator + directory + File.separator + fileName); 126 os = new FileOutputStream(file, isAppend); 127 if (encoding.equals("")) { 128 os.write(content.getBytes()); 129 } else { 130 os.write(content.getBytes(encoding)); 131 } 132 os.flush(); 133 } catch (IOException e) { 134 Log.e("FileUtil", "writeToSDCardFile:" + e.getMessage()); 135 } finally { 136 try { 137 if (os != null) { 138 os.close(); 139 } 140 } catch (IOException e) { 141 e.printStackTrace(); 142 } 143 } 144 return file; 145 } 146 147 /** 148 * write data from inputstream to SDCard 149 */ 150 public static File writeToSDCardFromInput(String directory, String fileName, 151 InputStream input) { 152 File file = null; 153 OutputStream os = null; 154 try { 155 if (createFile(directory)) { 156 return file; 157 } 158 file = new File(Environment.getExternalStorageDirectory() 159 + File.separator + directory + File.separator + fileName); 160 os = new FileOutputStream(file); 161 byte[] data = new byte[bufferd]; 162 int length = -1; 163 while ((length = input.read(data)) != -1) { 164 os.write(data, 0, length); 165 } 166 // clear cache 167 os.flush(); 168 } catch (Exception e) { 169 Log.e("FileUtil", "" + e.getMessage()); 170 e.printStackTrace(); 171 } finally { 172 try { 173 os.close(); 174 } catch (Exception e) { 175 e.printStackTrace(); 176 } 177 } 178 return file; 179 } 180 181 public static String ReadFromSDCardFile(String directory,String fileName){ 182 String res=""; 183 File file = null; 184 file = new File(Environment.getExternalStorageDirectory() 185 + File.separator + directory + File.separator + fileName); 186 try { 187 FileInputStream fis = new FileInputStream(file); 188 int length = fis.available(); 189 byte [] buffer = new byte[length]; 190 fis.read(buffer); 191 res = EncodingUtils.getString(buffer, "UTF-8"); 192 fis.close(); 193 return res; 194 }catch (FileNotFoundException e) { 195 // TODO Auto-generated catch block 196 Log.d("TEST", "FileNotFound"); 197 e.printStackTrace(); 198 }catch (Exception e) { 199 Log.d("TEST", "Can Not Open File"); 200 e.printStackTrace(); 201 } 202 return null; 203 } 204 }
资源下载:DataDemo
参考文章:(1)Android中的SharedPreferences存储数据方式 http://blog.csdn.net/zuolongsnail/article/details/6556703 (2)Android - 文件操作 小结 http://www.open-open.com/lib/view/open1330957864280.html限于篇幅,这篇文章就到此结束,这篇主要讲了如何在Android中读写文件,包括SDCard中和应用内部的文件。以及如何使用设置文件。在下一篇我会讲解Android内部自带的数据库使用及操作。========================================
作者:cpacm
出处:(http://www.cpacm.net/2015/03/22/Android开发日记(五)——Android数据存储(上)/)