一、Android 中的文件读取
1.读取 Android Project 下的文件
Android 资源管理框架实际就是由 AssetManager 和 Resources 两个类来实现的。其中,Resources 类可以根据 ID来 查找资源,而 AssetManager 类根据文件名来查找资源。如果一个资源 ID 对应的是一个文件,那么 Resources 类是先根据 ID 来找到资源文件名称,然后再将该文件名称交给 AssetManager 类来打开对应的文件的,这个过程下图所示。
在上图中,Resources 类根据资源 ID 来查到资源名称实际上也是要通过AssetManager 类来实现的,这是因为资源 ID 与资源名称的对应关系是由打包在APK 里面的 resources.arsc 文件中的。当 Resources 类查找的资源对应的是一个文件的时候,它就会再次将资源名称交给 AssetManager,以便后者可以打开对应的文件,否则的话,上一步找到的资源名称就是最终的查找结果,详细介绍见 Android应用程序资源的查找过程分析。
Resources 类资源如图片 drawable、布局 layout、字符串 string、动画 anim等,放在 Project 根目录的 res 子目录下。读取这类的文件资源使用相应的Id就行,比如读取一个图片资源 drawable:R.drawable.xxx。非 Resources 类的资源文件读取就需要通过 AssetManager 类来读取了,这类资源放在 Project 根目录的 assets 子目录下,与 res 同级目录,它里面保存的是一些原始的文件,可以以任何方式来进行组织,文件这些仅仅是纯文本。比如想要读取Project中的一个.json文件,则需要先创建一个与res同级目录的 assets 目录,并将 config.json 放在该目录下:
然后在代码中读取 config.json 文件。
assets 读取 project 中 config.json 文件:
private void loadConfigDataByFile() {
AssetManager am = getAssets(); //获取一个AssetManager用于读取filename为config.json的文件
try {
InputStream inputStream = am.open("config.json");
ByteArrayOutputStream os = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int len = -1;
while ((len = inputStream.read(buffer)) != -1) {
os.write(buffer, 0, len);
}
inputStream.close();
String state = os.toString();// 把流中的数据转换成字符串,采用的编码是utf-8(模拟器默认编码)
appPopUpConfig = new Gson().fromJson(state, AppPopUpConfig.class);
os.close();
} catch (IOException e) {
e.printStackTrace();
}
}
注意:若在Android Project中把config.json文件放在了非assets目录下,并用文件读取方式(如FileReader)去读取就会报FileNotFound错误,比如放在如下位置:
2.读取本地 sdcard 中的文件
首先,最重要的一步,在 AndroidManifest.xml 添加 sdcard 权限,不然所有的都会白搭(关于 sdcard 权限设置有话说:Android 6.0 权限适配之WRITE_EXTERNAL_STORAGE):
然后代码中读取文件,假设想读取一张本地 sdcard 图片,通常会这样写:
获取本地 sdcard 图片:
private Bitmap getDiskBitmap(String pathString) {
Bitmap bitmap = null;
try {
File file = new File(pathString);
if (file.exists()) {
bitmap = BitmapFactory.decodeFile(pathString);
}
} catch (Exception e) {
Log.e("Exception: ", e.toString());
}
return bitmap;
}
问题来了,pathString 要怎样写?在 Android Studio 的 Android Device Mointor查看设备的文件结构,若读取 images.jpeg 图片,根据文件结构,pathString="/mnt/shell/emulated/0/DCIM/images.jpeg",但结果并没有那个美好,读取出来的 bitmap 为 null,故该方式写路径 pathString 错误。
换个正确的姿势写路径 pathString:
//方式一:调用函数获取sdcard路径
private String mSdRootPath = Environment.getExternalStorageDirectory().getPath(); //sdcard卡的根目录
private String mFilePath = "/DCIM/images.jpeg";
String pathString = mSdRootPath + mFilePath;
//方式二:简单粗暴直接写
String pathString ="/sdcard/DCIM/images.jpeg";
为何将 "/mnt/shell/emulated/0/DCIM/images.jpeg" 前面一串换成 /sdcard 就能正确读取图片文件了呢?从上图标注的红色箭头可以看到,sdcard 文件链接到了storage/emulated/legacy,storage/emulated/legacy 链接到了 /mnt/shell/emulated/0,所以我们以 /sdcard 作为路径起始位置,就能正确读取出images.jpeg 了。
二、Java 中的文件读取
1.读取 Java Project 下的文件
读取文件,首先需获取文件的路径,先理清以下绝对路径和相对路径。相对路径就是相对与其他文件的路径。比如有以下这么一个文件:
MyClass.java文件的绝对路径是 javaproject/src/main/java/com/example/MyClass,config.json文件的绝对路径是 javaproject/src/main/java/config.json。那么 MyClass.java 相对于 config.json 的路径就是 com/example/MyClass(也可以写成这种形式:.com/example/MyClass)。”.” 的意思是当前目录,也就是 MyClass.java 所相对的文件所在的目录,在这里就是:javaproject/src/main/java/。
比如要读取上图中的 config.json 文件,则
读取 project 中 config.json 文件:
public static String readByFileReader() {
String fileContent = null;
try {
String line = null;
StringBuilder strBuffer = new StringBuilder();
BufferedReader bufferedReader = new BufferedReader(new FileReader("javaproject/src/main/java/com/example/config.json")); //路径要从根目录javaproject写起
while ((line = bufferedReader.readLine()) != null) {
strBuffer.append(line);
}
bufferedReader.close();
fileContent = strBuffer.toString();
} catch (IOException e) {
e.printStackTrace();
}
return fileContent;
}
注意第6行,config.json的路径必须写全,从项目的根目录写起,不然会报FileNotFound错误。看网上很多说在Java Project中可以用相对路径读取文件,然而在Android Studio中实验,结果并不是,路径不写全都会报错...
2.读取磁盘中的文件
读取磁盘的文件,与读取 Project 下的文件类似,只是写路径的方式有点区别。以绝对路径方式读取磁盘文件,并以盘符开始的,例如读取磁盘 C:/workspace/android/javaproject/data.txt 文件。
读取磁盘中 data.txt 文件:
public static void readFileByBytes() {
String fileName = "C:/workspace/android/javaproject/data.txt"; //路径从磁盘符写起
File file = new File(fileName);
String name = file.getName();
InputStream in = null;
try {
System.out.println("以字节为单位读取文件内容,一次读一个字节:");
// 一次读一个字节
in = new FileInputStream(file);
int tempbyte;
while ((tempbyte = in.read()) != -1) {
System.out.write(tempbyte);
}
in.close();
} catch (IOException e) {
e.printStackTrace();
return;
}
try {
System.out.println("以字节为单位读取文件内容,一次读多个字节:");
// 一次读多个字节
byte[] tempbytes = new byte[100];
int byteread = 0;
in = new FileInputStream(fileName);
// 读入多个字节到字节数组中,byteread为一次读入的字节数
while ((byteread = in.read(tempbytes)) != -1) {
System.out.write(tempbytes, 0, byteread);
}
} catch (Exception e1) {
e1.printStackTrace();
} finally {
if (in != null) {
try {
in.close();
} catch (IOException e1) {
}
}
}
}
根据路径读取到文件后,更多关于文件流的读取详细介绍可点这里,具体用法。
3.读取 classpath 下的文件
什么是 classpath(类路径)?假设我们在 Android Studio 中有一个 Java 工程:javaproject,在工程 javaproject 下边会自动创建两个目录:src 和 build。这个build 目录(包括 web 应用中 WEB-INF 下的 classes 目录)就统称为classpath。对于类路径下的文件,可以采取以下方式:
TODO:http://blog.csdn.net/jiaobuchong/article/details/52422954(读取结果有错)
参考链接:
http://blog.csdn.net/luoshengyang/article/details/8738877
http://www.cnblogs.com/caowei/p/2013-12-03_fileread.html