数据访问(src、assets、res读取)以及app安装路径

第二节 数据访问

  Android项目中有三个比较重要的文件夹:srcassetsres,本节将依次介绍如何获取上述三个文件夹内的文件。

ClassLoader

  在JavaSE中通常都会使用ClassLoader(类加载器)来访问src文件夹下的某个文件,在Android中也是同样如此。


  问:什么是类加载器?
  答:虚拟机若想运行某一个类,则必须先将其加载入内存,而加载类到内存的工具,就是类加载器。换句话说,每一个存在于虚拟机(不论是JVM还是Dalvik)中的类,都是被类加载器载入内存的。


  再问:类加载器的功能还有什么?
  再答:类加载器除了可以加载字节码文件,还可以加载其他文件,只要该文件存在于类加载器所在的工作目录下面即可。


  还问:类加载器的工作目录是哪个目录?
  还答:类加载器有多种,每种加载器的所加载的类是不同的。如:boot类加载器加载Java核心类库中的类(String类等)。 app类加载器:加载用户自定义的类。它们两个类加载器的工作目录是不一样的。


  接着问:如何获取一个ClassLoader对象呢?
  接着答:所有的类都是被类加载加载到内存的,在Java中使用Class类来代表字节码,通过某个类的Class对象就可以获取该类的加载器。


  范例1:Class类。

     
     
1
2
     
     
// 返回当前Class对象所代表的类的类加载器。若此对象表示一个基本类型或void,则返回 null。
public ClassLoader getClassLoader()


  范例2:获取int的类加载器。

     
     
1
     
     
System.out.println( int.class.getClassLoader()); // 输出null。


  范例3:加载文件。

     
     
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
     
     
public class AndroidTestActivity extends Activity {
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
// 获取AndroidTestActivity的类加载器,由于该类是自定义的类,因此其类加载器是app。
InputStream input = getClassLoader().getResourceAsStream( "a.txt");
try{
System.out.println( "content="+ this.readFile(input));
} catch(Exception e){
e.printStackTrace();
}
}
private String readFile(InputStream input) throws Exception{
String resultStr = null;
ByteArrayOutputStream out = new ByteArrayOutputStream();
int len;
byte[] array = new byte[ 1024];
while ((len = input.read(array)) != - 1) {
out.write(array, 0,len);
}
resultStr = out.toString( "UTF-8"); // 可以不写UTF-8,默认就为UTF-8。
input.close();
out.close();
return resultStr;
}
}
语句解释:
-  首先在src根目录下面建立一个a.txt ,内容为:Hi Android世界。
-  若程序执行的时候出现了乱码,请检查您Android项目的编码是否使用的UTF-8


  范例4:加载文件2.0 。

     
     
1
     
     
InputStream input=getClassLoader().getResourceAsStream( "org/cxy/test/b.txt");
语句解释:
-  首先在src目录下面的org.cxy.test包下面建立一个b.txt。
-  若需要访问某个包中的文件,则需要将包名中的“.”换成路径分隔符“/”。但是文件后缀名中的“.”不需要换。 
-  Andoird是基于Linus内核的,因此不可使用“\\”作为路径分隔符,因为那是Windows中使用的。


类装载器缺点

-  第一,类装载器会将文件一次性全部读入内存后再处理。
-  第二,类装载器,对于一个文件只会装载一次,若文件的内容在程序运行的时候被更新,则程序无法及时获得新的数据。


  范例5:思考题,下面File对象的相对路径相对于谁?。

     
     
1
2
3
4
5
6
7
8
9
10
11
12
13
     
     
package org.cxy.test;
import java.io.File;
import android.app.Activity;
import android.os.Bundle;
public class AndroidTestActivity extends Activity {
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
File file = new File( "a.txt");
System.out.println(file.exists());
}
}
语句解释:
-  答:相对于用户手机的根目录“/”,而不是apk包的根目录。
-  前面已经说了,用户手机中存在有三个目录:system、data、mnt ,这三个目录就是存在于根目录“/”下面的。
-File对象的构造方法中指定的路径是以“/”开头,则意味着该路径是绝对路径。
-  若在某个应用程序中想访问其他应用程序的文件(前提是该文件允许你访问他),就可以使用绝对路径的方式:
   -  如:/data/data/org.cxy.file/files/a.txt 。

AssetManager

  在Android中可以使用AssetManager类来访问assets目录下的文件。assets目录的特点:

-  首先,assets文件夹内单个文件的大小必须<=1MB 。
-  然后,assets文件夹内的文件不会被注册到R文件中。
-  接着,assets文件夹内可以任意自定义子文件夹。
-  最后,assets文件夹主要用于保存一些“容量小且固定不变”的文件,如:游戏音乐等。所谓的“固定不变”指的是在程序运行的时候,该文件仅会被程序读取而不会去修改其内容。 


  范例1:获取输入流。

     
     
1
2
3
4
5
6
7
8
9
10
11
12
13
14
     
     
public class AndroidTestActivity extends Activity {
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
try {
// 获取一个AssetManager对象。
AssetManager manager = getAssets();
// open方法用来从asset目录下获取指定文件的输入流。
System.out.println( this.readFile(manager.open( "a.txt")));
} catch (Exception e) {
e.printStackTrace();
}
}
}
语句解释:
-  为了减少篇幅,笔者把readFile方法具体实现给省略了。


  范例2:遍历所有文件。

     
     
1
2
3
4
5
6
7
8
     
     
public void test(){
String folder= "a";
AssetManager manager = getAssets();
for(String name:manager.list(folder)){
System. out.println(name);
System. out.println(readFile(manager.open(folder+File.separator+name)));
}
}
语句解释:
-  本范例中“manager.list(folder)”的含义为:将"assets/a"目录下面的所有文件的文件名称列出来。
-  将文件的路径path与list方法返回的文件的名称组合在一起后,就可以调用open方法获取该文件的输入流了。

第三节 App安装位置

  从API level 8开始,可以通过在manifest中声明android:installLocation属性,来将应用程序安装到外部存储设备中,如果不使用该属性,则应用默认只会安装在手机内存中。


  例如:

     
     
1
2
3
     
     
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
android:installLocation= "preferExternal"
... >

  如果该属性值设为preferExternal,表明用户要求应用程序优先安装在外部存储设备中,但是系统并不保证应用程序真的安装在外部存储设备中。如果外部存储设备的空间已满,系统仍然会将应用程序安装在内存中。用户也可以在两个位置之间移动应用程序。
  如果该属性值设为auto,表明应用程序可能安装在外部存储设备中,但是用户本身对安装位置没有特殊要求。系统会根据多种因素决定将应用程序安装在哪里。用户也可以在两个位置之间移动应用程序。


  当应用程序安装在外部存储设备中时:

-  只要外部存储设备装载在设备上,应用程序的性能就不会受到影响。
-  .apk文件是保存在外部存储设备中的,但是所有的私有用户数据、数据库、优化的.dex文件和提取的本地代码都是保存在设备的内存中的。
-  保存应用程序的唯一容器经过一个随机产生的密钥进行加密。该密钥只能由最初安装该程序的设备解密。因此,安装在SD卡上的应用程序只能在某一个固定的设备上运行。
-  用户可以通过系统设置将应用程序移动到内存上。


  注意:

-  当用户使用USB大容量存储器与计算机共享文件时,或通过系统设置卸载SD卡时,外部存储设备将从本设备卸载,并且所有在该外部存储设备中安装的应用程序将立刻被关闭。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值