安卓文件存储的小小总结


安卓四大存储之文件存储


四大存储方式,其实是五大,因为网络云存储也已经普及得挺快的。不过这里先谈谈文件存储,也看过很多的博文,和一些零星的观点。但是网上的资料真的是找shi爹了。所以还是自己写点总结。

关于存储的问题

因为手机的ROM一般都是固定的,所以我们应该珍惜它的容量。 Android本身来讲是一个Linux操作系统,所以它的内部存储空间,对于应用程序和用户来讲就是“/data/data"目录。它与其他的(外部的存储)相比肯定是有着比较稳定,存储方便,操作简单,更加安全(因为可以控制访问权限)等优点。而它唯一的缺点就是它比较有限,比较可贵。
虽然,可以非常容易的知道程序本身的数据所在路径,所有的应用程序的数据路径都是“/data/data/app-package-name/”,所有的程序用到的数据,比如libs库,SharedPreferences都是存放在这个路径下面。但我们在使用的时候最好不要,或是千万不要直接引用这个路径。 

使用内部存储主要有二个方式,一个是文件操作,一个是文件夹操作。无论哪种方式,Context中都提供了相应的函数来支持,使用Context不但操作简单方便,最重要的是Context会帮助我们管理这些文件,也可以方便帮助我们控制文件的访问权限。先来系统的说下Context中关于文件和文件夹操作的函数有哪些。 

再来谈谈手机外部存储空间,与内部存储空间相对,外部存储空间是指手机出厂的时候不存在,用户在使用时候可以自由添加的外部存储介质比如TS卡,SD卡等闪存储介质。这些闪存介质由最初的空间小价格贵,到现在的大容量价格便宜,所以几乎每个支持外部存储的手机上面都有大容量(大于等于2G)的闪存卡。 

Android也是不例外,它完全支持外部存储介质。其实更确切的说,它是要依赖于外部存储卡的,因为对于Android系统,如果没有外部存储卡,很多的系统应用无法使用,比如多媒体相关的应用程序无法使用。虽然Android很依赖,但是外部存储卡也有它自身的特点,它最大的优点就是存储空间大,基本上你可无限制的使用,也不怎么担心去清除数据。就目前来看,很多程序都在使用外部存储卡,但很少有程序去主动清理数据,所以无论你的SD卡有多大,它的可用空间却越来越少。与内部存储不同的是,当程序卸载时,它在外部存储所创建的文件数据是不会被清除的。所以清理外部存储空间的责任丢给了用户自己,每隔一段时间就去查看下SD卡,发现无用数据立马删除。外部存储的缺点就是不是很稳定,对于Android手机来讲可以说,很不稳定,本身闪存介质就容易出问题,SD卡处于不能正常使用的状态十分多。  

如果你使用API 8(Android 2.2)或者更高,那么SDK中又多了几个操作外部存储文件和路径的接口,文档中也建议开始者更加规范的使用SD卡。比如,创建相应的目录去存储相应的数据,Music,Picture,Video等。应用程序目录也变成了"/Android/data/package-name/data"。具体的使用可以参考文档,这里不重复。当然,就像编程规范一样,这里只是规范,你完全可以不遵守它,但出于可读性和可移植性,还是建议按照文档建议的去做。 
同时感谢博文: http://ipjmc.iteye.com/blog/1447097

下面总结一下使用时应该注意的一些和外部存储的特点: 

a. 外部存储卡不是随时想用就能够用的,所以一定要记得在使用之前检查它的可用性 

b. 存储在外部存储卡上的数据是所有应用程序都可见,用户也可见(使用FileManager),所以安全性不是很好,虽然文档声称可以在外部存储卡上写程序私有数据,但貌似没用,用FileManager仍然可以删除或编辑文件(Market上面的FileManager功能都十分的强大,能让用户看到SD卡中的所有文件,和操作能看到的文件)。 

c. Android手机支持把外部存储卡Mount至PC做为U盘,当连接数据线时,这时SD卡变成了U盘连接到了另外的操作系统中。什么意思,就是在Android当中虽然有的文件属性(隐藏,私有等),到了PC上就不一定管用了,用户在PC上可以随意操作文件(这就是第二点中所提及的)。 


d. 如果使用外部存储卡保存数据,一定要额外做好异常处理:外部存储卡不可用时把数据存入哪里;可用的时候再怎么同步数据(这是比较头疼的地方,可行的做法就是当SD卡不可用时不准用户写数据,但这用户体验又不是很好,但如你所知,很多应用都这么干);你的数据被破坏了。当然常见的异常也要考虑,比如空间满了,无法写入,磁盘坏道等。 
我们还可以看一下常见的文件目录: 

别忘了权限 

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


因为文件操作基本上都是流的操作,所以总结一下,流的操作InputStream和OutputStream是相对于内存而言,所以无论是拷贝到ROM还是SD卡,都是输出。但是从assets目录下拷贝出去的是从内存拷出,所以需要InputStream来进行流操作。


本章总结从ROM对RAM,SDCARD对RAM的操作:

我喜欢这个官方规范

 /mnt/sdcard/Android/data/zy.zh.filedemo/cache

该目录在程序卸载后会自动删除

/*****
 * 文件操作类
 * 
 * @author 
 * 
 */
public class FileService {
	/**
	 * 上下文对象
	 */
	private Context context;
	/**
	 * SD卡目录
	 */
	private File fileSD;

	/**
	 * 检测SD卡存在,并且可写
	 */
	public boolean existSDCard() {
		return (Environment.getExternalStorageState()
				.equals(Environment.MEDIA_MOUNTED));
	}

	// /mnt/sdcard/Android/data/zy.zh.filedemo/cache
	// 该目录在程序卸载后会自动删除
	public FileService(Context context) {
		super();
		this.context = context;
		// File file = new File(Environment.getExternalStorageDirectory(),
		// "Android");
		// file = new File(file, "data");
		// file = new File(file,context.getPackageName());
		// fileSD = new File(file, "cache");
		// 以上注释也是可以用的
		fileSD = new File(Environment.getExternalStorageDirectory()
				+ "/Android/data/" + context.getPackageName() + "/cache");
		if (!fileSD.exists()) {
			if (!fileSD.mkdirs()) {
				return;
			}
		}
		try {
			new File(fileSD, ",nomedia").createNewFile();// 建立文件
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	/**
	 * 保存文件至手机自带的存储空间ROM中
	 */
	@SuppressWarnings("static-access")
	public void save(String filename, String fileContent) throws Exception {
		FileOutputStream fos = context.openFileOutput(filename,
				context.MODE_PRIVATE); // 默认保存在手机自带的存储空间
		fos.write(fileContent.getBytes("UTF-8"));
		fos.close();
	}

	/**
	 * 读取文件内容,从ROM空间中读取
	 */
	public String read(String filename) throws Exception {
		FileInputStream fis = context.openFileInput(filename);
		ByteArrayOutputStream outStream = new ByteArrayOutputStream();
		byte[] buffer = new byte[1024];
		int len = 0;
		// 将内容读到buffer中,读到末尾为-1
		while ((len = fis.read(buffer)) != -1) {
			// 本例子将每次读到字节数组(buffer变量)内容写到内存缓冲区中,起到保存每次内容的作用
			outStream.write(buffer, 0, len);
		}
		// 取内存中保存的数据
		byte[] data = outStream.toByteArray();
		fis.close();
		String result = new String(data, "UTF-8");
		return result;
	}

	/**
	 * 保存文件至SD卡
	 */
	public void saveInSDCard(String filename, String fileContent)
			throws Exception {
		File file = new File(fileSD, filename);
		FileOutputStream fos = new FileOutputStream(file);
		fos.write(fileContent.getBytes("UTF-8"));
		fos.close();
	}

	/**
	 * 读取SD卡中文本文件
	 */
	public String readSDFile(String fileName) {
		StringBuffer sb = new StringBuffer();
		File file = new File(fileSD, fileName);
		try {
			FileInputStream fis = new FileInputStream(file);
			int c;
			while ((c = fis.read()) != -1) {
				sb.append((char) c);
			}
			fis.close();
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		return sb.toString();
	}

	/**
	 *  删除rom中的文件
	 */
	public void delFileInRom(String fielName) {
		File file = new File(context.getFilesDir(), fielName);
		if (file.exists()) {
			boolean result = file.delete();
			Log.i(getClass().getSimpleName(), "删除 result=" + file.getPath()
					+ "=" + result);
		}
	}

	/**
	 * 删除SD卡的文件
	 */
	public void delFileInSDcard(String filename) {
		File file = new File(fileSD, filename);
		if (file.exists()) {
			boolean result = file.delete();
			Log.i(getClass().getSimpleName(), "删除 result=s" + file.getPath()
					+ "=" + result);
		}
	}

	public void testDir() {
		LOGI("getFilesDir()=" + context.getFilesDir().getPath());
		LOGI("getCacheDir()=" + context.getCacheDir().getPath());
		LOGI("getExternalCacheDir()=" + context.getExternalCacheDir().getPath());
		LOGI("getDataDirectory()="+Environment.getDataDirectory().getPath());
	}

	private void LOGI(String text) {
		Log.i(getClass().getSimpleName(), text);
	}

}
输出系统路径为:



转载请联系作者并注明出处:http://blog.csdn.net/dreamintheworld/article/details/38542417



  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值