其实安卓文件的操作和java在pc环境下的操作并无二致,之所以需要单独讲解是因为安卓系统提供了不同于pc的访问文件系统根路径的api,同时对一个应用的私有文件做了统一的管理。初学者在这部分感到很容易混淆内部存储和外部存储两个概念。

相对路径和绝对路径

  在java中,关于相对路径和绝对路径是这样解释的。

  绝对路径是指书写文件的完整路径,例如d:\java\Hello.java,该路径中包含文件的完整路径d:\java以及文件的全名Hello.java。使用该路径可以唯一的找到一个文件,不会产生歧义。但是使用绝对路径在表示文件时,受到的限制很大,且不能在不同的操作系统下运行,因为不同操作系统下绝对路径的表达形式存在不同。

  相对路径是指书写文件的部分路径,例如\test\Hello.java,该路径中只包含文件的部分路径\test和文件的全名Hello.java,部分路径是指当前路径下的子路径,例如当前程序在d:\abc下运行,则该文件的完整路径就是d:\abc\test。使用这种形式,可以更加通用的代表文件的位置,使得文件路径产生一定的灵活性。

  在Eclipse项目中运行程序时,当前路径是项目的根目录,例如工作空间存储在d:\javaproject,当前项目名称是Test,则当前路径是:d:\javaproject\Test。在控制台下面运行程序时,当前路径是class文件所在的目录,如果class文件包含包名,则以该class文件最顶层的包名作为当前路径。

  这是java在多数操作系统中这样操作,很显然是要我们尽可能的使用相对路径,但是在安卓中,其实多数情况下我们都是使用的绝对路径。为什么呢?注意上面说到相对路径是以当前项目所在路径为当前路径,但在安卓中我们是不可能在项目所在路径目录下做任何操作的,因为普通java中我们的项目创建于服务器(pc也算是服务器),运行于服务器,我们当然能在服务器操作自己的文件目录。但是安卓开发中,我们的项目一般是创建于自己工作的电脑,而运行于手机,既然apk已经运行于手机了,那项目就已经部署到手机上了,应该以apk在手机上的位置来确定相对路径,但我们好像们没有办法操作这个路径的,因为apk是在system目录下,就算可以操作,在这个目录下存取文件也是没有意义的,比如我写一个相册程序,图片肯定是放在外部存储中,而如果我要保存一个应用的一些设置数据,我是放在内部存储的data目录下,因此其实在安卓文件管理中,我们都是在操作绝对路径。

File类

操作一个文件(读写,创建文件或者目录)是通过File类来完成的,这个操作和java中完全一致。

外部存储external storage和内部存储internal storage

1.内部存储:

  注意内部存储不是内存。内部存储位于系统中很特殊的一个位置,如果你想将文件存储于内部存储中,那么文件默认只能被你的应用访问到,且一个应用所创建的所有文件都在和应用包名相同的目录下。也就是说应用创建于内部存储的文件,与这个应用是关联起来的。当一个应用卸载之后,内部存储中的这些文件也被删除。从技术上来讲如果你在创建内部存储文件的时候将文件属性设置成可读,其他app能够访问自己应用的数据,前提是他知道你这个应用的包名,如果一个文件的属性是私有(private),那么即使知道包名其他应用也无法访问。 内部存储空间十分有限,因而显得可贵,另外,它也是系统本身和系统应用程序主要的数据存储所在地,一旦内部存储空间耗尽,手机也就无法使用了。所以对于内部存储空间,我们要尽量避免使用。Shared Preferences和SQLite数据库都是存储在内部存储空间上的。内部存储一般用Context来获取和操作。

getFilesDir()获取你app的内部存储空间,相当于你的应用在内部存储上的根目录。

  如果是要创建一个文件,如下:File file = newFile(context.getFilesDir(), filename);

安卓还为我们提供了一个简便方法 openFileOutput()来读写应用在内部存储空间上的文件,下面是一个向文件中写入文本的例子:

String filename = "myfile";
String string = "Hello world!";
FileOutputStream outputStream;
try{
  outputStream = openFileOutput(filename,Context.MODE_PRIVATE);
  outputStream.write(string.getBytes());
  outputStream.close();
} catch(Exception e) {
  e.printStackTrace();
}

内部存储的其他一些操作:

A.列出所有的已创建的文件,这个可能不容易想到,Context居然有这样的方法。

String[] files = Context.fileList();
for(String file : files) {
  Log.e(TAG, "file is "+ file);
}

B.删除文件,能创建就要能够删除,当然也会提供了删除文件的接口,它也非常简单,只需要提供文件名

if(Context.deleteFile(filename)) {
  Log.e(TAG, "delete file "+ filename + " sucessfully“);
}
else {
Log.e(TAG, "failed to deletefile " + filename);
}

C.创建一个目录,需要传入目录名称,它返回 一个文件对象用到操作路径

File workDir = Context.getDir(dirName, Context.MODE_PRIVATE);
Log.e(TAG, "workdir "+ workDir.getAbsolutePath();

总结一下文件相关操作,可以得出以下三个特点:
1. 文件操作只需要向函数提供文件名,所以程序自己只需要维护文件名即可;
2. 不用自己去创建文件对象和输入、输出流,提供文件名就可以返回File对象或输入输出流
3. 对于路径操作返回的都是文件对象。

2.外部存储:

  最容易混淆的是外部存储,如果说pc上也要区分出外部存储和内部存储的话,那么自带的硬盘算是内部存储,U盘或者移动硬盘算是外部存储,因此我们很容易带着这样的理解去看待安卓手机,认为机身固有存储是内部存储,而扩展的T卡是外部存储。比如我们认为16GB版本的Nexus 4有16G的内部存储,普通消费者可以这样理解,但是安卓的编程中不能,这16GB仍然是外部存储。

  所有的安卓设备都有外部存储和内部存储,这两个名称来源于安卓的早期设备,那个时候的设备内部存储确实是固定的,而外部存储确实是可以像U盘一样移动的。但是在后来的设备中,很多中高端机器都将自己的机身存储扩展到了8G以上,他们将存储在概念上分成了"内部internal" 和"外部external" 两部分,但其实都在手机内部。所以不管安卓手机是否有可移动的sdcard,他们总是有外部存储和内部存储。最关键的是,我们都是通过相同的api来访问可移动的sdcard或者手机自带的存储(外部存储)。

  外部存储虽然概念上有点复杂,但也很好区分,你把手机连接电脑,能被电脑识别的部分就一定是外部存储。

  外部存储中的文件是可以被用户或者其他应用程序修改的,有两种类型的文件(或者目录):

  1.公共文件Public files:文件是可以被自由访问,且文件的数据对其他应用或者用户来说都是由意义的,当应用被卸载之后,其卸载前创建的文件仍然保留。比如camera应用,生成的照片大家都能访问,而且camera不在了,照片仍然在。

如果你想在外存储上放公共文件你可以使用getExternalStoragePublicDirectory()

public File getAlbumStorageDir(String albumName) {
  // Get the directory for the user's public pictures directory.
  File file = newFile(Environment.getExternalStoragePublicDirectory(
  Environment.DIRECTORY_PICTURES), albumName);
  if(!file.mkdirs()) {
    Log.e(LOG_TAG, "Directory not created");
  }
  return file;
}

在上面的代码中我们创建获得了存放picture的目录,并且新创建一个albumName文件。

如果你的api 版本低于8,那么不能使用getExternalStoragePublicDirectory(),而是使用Environment.getExternalStorageDirectory(),他不带参数,也就不能自己创建一个目录,只是返回外部存储的根路径。

  2.私有文件Private files:其实由于是外部存储的原因即使是这种类型的文件也能被其他程序访问,只不过一个应用私有的文件对其他应用其实是没有访问价值的(恶意程序除外)。外部存储上,应用私有文件的价值在于卸载之后,这些文件也会被删除。类似于内部存储。

创建应用私有文件的方法是Context.getExternalFilesDir(),如下:

public File getAlbumStorageDir(Context context, String albumName) {
  // Get the directory for the app's private pictures directory.
  File file = newFile(context.getExternalFilesDir(
  Environment.DIRECTORY_PICTURES), albumName);
  if(!file.mkdirs()) {
    Log.e(LOG_TAG, "Directory not created");
  }
  return file;
}

上面的代码创建了一个picture目录,并在这个目录下创建了一个名为albumName的文件,Environment.DIRECTORY_PICTURES其实就是字符串picture。

所有应用程序的外部存储的私有文件都放在根目录的Android/data/下,目录形式为/Android/data/<package_name>/

如果你的api 版本低于8,那么不能使用getExternalFilesDir(),而是使用Environment.getExternalStorageDirectory()获得根路径之后,自己再想办法操作/Android/data/<package_name>/下的文件。

也就是说api 8以下的版本在操作文件的时候没有专门为私有文件和公共文件的操作提供api支持。你只能先获取根目录,然后自行想办法。

在使用外部存储之前,你必须要先检查外部存储的当前状态,以判断是否可用。

boolean mExternalStorageAvailable = false;
boolean mExternalStorageWriteable = false;
String state = Environment.getExternalStorageState();
if(Environment.MEDIA_MOUNTED.equals(state)) {
  // We can read and write the media
  mExternalStorageAvailable = mExternalStorageWriteable = true;
} else if(Environment.MEDIA_MOUNTED_READ_ONLY.equals(state)) {
  // We can only read the media
  mExternalStorageAvailable = true;
  mExternalStorageWriteable = false;
} else{
  // Something else is wrong. It may be one of many other states, but all we need
  // to know is we can neither read nor write
  mExternalStorageAvailable = mExternalStorageWriteable = false;
}

Android中的内存储、外存储概念、文件操作与PC端的有些不同的更多相关文章

  1. Android中的5种数据存储方式

    本文转自  http://hi.baidu.com/maguowei/blog/item/7aca46c25574a33ae5dd3ba4.htmlAndroid数据存储Android提供了5种方式存 ...

  2. 在Android中访问内置SE和基于SE的卡模拟(一)

    2013-10-10 编写 前言 在“十问Android NFC手机上的卡模拟”文中仅仅简单的介绍了一下相关的概念,如果需要了解基于SE的卡模拟的更多细节,也就是,究竟在Android的NFC手机上, ...

  3. Android中StatFs获取系统/sdcard存储(剩余空间)大小

    1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 3 ...

  4. SQL中的内连接外连接和交叉连接是什么意思?

    内连接又分为等值连接.自然连接和不等连接三种. 外连接分为左外连接(LEFT OUTER JOIN或LEFT JOIN).右外连接(RIGHT OUTER JOIN或RIGHT JOIN)和全外连接( ...

  5. kali linux android木马(内网+外网)

    1,内网木马 先生成一个小马 msfpayload -p android/meterpreter/reverse_tcp LHOST=192.168.8.104 LPORT=5555 R > a ...

  6. 探讨Android中的内置浏览器和Chrome

    1.Android默认浏览器和Chrome的区别 Android出厂自带的浏览器:安卓WebKit浏览器,也成内置浏览器或者默认浏览器. 安卓WebKit不是Chrome.Chrome浏览器在它的用户 ...

  7. mysql中的内连接,外连接实例详解

    内连接: 只连接匹配的行左外连接: 包含左边表的全部行(不管右边的表中是否存在与它们匹配的行),以及右边表中全部匹配的行右外连接: 包含右边表的全部行(不管左边的表中是否存在与它们匹配的行),以及左边 ...

  8. Android中使用Apache common ftp进行下载文件

    版权声明:本文为博主原创文章,未经博主同意不得转载. https://blog.csdn.net/birdsaction/article/details/36379201 在Android使用ftp下 ...

  9. python中用json存储列表字典等文件操作

    JSON字符串用json.dumps, json.loads JSON文件名用json.dump, json.load 由于需要在脚本重启后依旧能够记住之前所使用的列表内容, 故采用json存储列表文 ...

随机推荐

  1. json中$ref对象重复引用问题

    FastJson提供了SerializerFeature.DisableCircularReferenceDetect这个序列化选项,用来关闭引用检测.关闭引用检测后,重复引用对象时就不会被$ref代 ...

  2. Intent组件的传参应用

    Intent是要执行的操作的抽象描述 可以在startActivity.startService等方法中使用 最为常见的用法是在Activity之间传递数据 跳转并传值: Intent intent= ...

  3. python 之初体验

    python 关开python的介绍我这里就不解释了,这里贴出一个官方的介绍,供大家阅读 http://baike.baidu.com/link?url=U6LdVR-5RCI2TNsXzeALCcG ...

  4. 01 选择 Help > Install New Software,在出现的对话框里,点击Add按钮,在对话框的name一栏输入“ADT”,点击Archive...选择离线的ADT文件,contact all update ....千万不要勾选点击Add按钮,在对话框的name一栏输入“ADT”,点击Archive...选择离线的ADT文件,contact all update ....千万不要勾

    引言 好久没碰过android,今天重新搭建了一次环境,遇到的问题记录下载.共以后使用. 安装 软件的软件有jdk+eclipse+adt+sdk 主要记录安装adt和sdk的过程,注意,adt和sd ...

  5. CentOS7 bonding配置

    操作系统:CentOS Linux release 7.1.1503 (Core) 网卡适配器: eno1.eno2 bonding类型:mode=1 (active-backup),主-备份策略 网 ...

  6. Version history of VC++, MFC and ATL

    I have tried to assemble together information about the Visual C++ releases, the compiler and the fr ...

  7. 使用 CXF 做 webservice 简单例子

    Apache CXF 是一个开放源代码框架,提供了用于方便地构建和开发 Web 服务的可靠基础架构.它允许创建高性能和可扩展的服务,您可以将这样的服务部署在 Tomcat 和基于 Spring 的轻量 ...

  8. C#可扩展编程之MEF学习笔记(二):MEF的导出(Export)和导入(Import)

    上一篇学习完了MEF的基础知识,编写了一个简单的DEMO,接下来接着上篇的内容继续学习,如果没有看过上一篇的内容, 请阅读:http://www.cnblogs.com/yunfeifei/p/392 ...

  9. PS 多次剪裁同一图片

    一个图品里面有两个小图,要分别抠出来. 我以前的做法是,先扣一个,重新打开文件,再扣另外一个. 今天发现一个简单的办法,不用重新打开文件. 就是在扣完第一个的时候,打开历史记录面板,双击 打开 动作, ...

  10. 《30天自制操作系统》笔记(01)——hello bitzhuwei’s OS!

    <30天自制操作系统>笔记(01)——hello bitzhuwei's OS! 最初的OS代码 ; hello-os ; TAB=4 ORG 0x7c00 ; 指明程序的装载地址 ; 以 ...