之前项目用到了文件存储相关的功能,功能基本都实现了,也满足了性能要求,在这里总结一下。
1.1. 读写应用程序目录下文件
Android ContextWrapper提供了openFileOutput和openFIleInput两个方法,可以读写
/data/data/应用程序包名 目录下的文件。
public FileOutputStreamopenFileOutput(String name, int mode)
name:文件名,不能包含路径分隔符“/”
mode:文件操作模式,有以下值:
MODE_PRIVATE:为默认操作模式,代表该文件是私有数据,只能被应用本身访问。
MODE_APPEND:模式会检查文件是否存在,存在就往文件追加内容,否则就创建新文件。
MODE_WORLD_READABLE:表示当前文件可以被其他应用读取;
MODE_WORLD_WRITEABLE:表示当前文件可以被其他应用写入。
openFileOutput()如果文件不存在,Android 会自动创建它。创建的文件保存在/data/data/应用程序包名/files目录下
public FileInputStream openFileInput(Stringname)
name:读取文件名
除此之外,Context还提供了如下几个重要的方法:
getDir(Stringname , int mode):在应用程序的数据文件夹下获取或者创建name对应的子目录
FilegetFilesDir():获取该应用程序的数据文件夹得绝对路径
String[]fileList():返回该应用数据文件夹的全部文件
private voidwrite1(String str, String fileName) {
try {
FileOutputStream out =openFileOutput(fileName, MODE_PRIVATE);
out.write(str.getBytes());
out.close();
Toast.makeText(MainActivity.this, "保存成功",Toast.LENGTH_SHORT).show();
} catch(Exception e) {
// TODOAuto-generated catch block
e.printStackTrace();
}
}
privateString read1(String fileName) {
try {
FileInputStream in =openFileInput(fileName);
int len= in.available();
byte[]temp = new byte[len];
in.read(temp);
String str = EncodingUtils.getString(temp,"UTF-8");
in.close();
return str;
} catch(Exception e) {
// TODOAuto-generated catch block
e.printStackTrace();
return null;
}
}
1.2. 读写sdcard上的文件
其中读写步骤按如下进行:
必须在AndroidManifest.xml上配置读写SD卡的权限
<uses-permissionandroid:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>
<uses-permissionandroid:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
1、调用Environment的getExternalStorageState()方法判断手机上是否插了sd卡,且应用程序具有读写SD卡的权限,如下代码将返回true
Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)
2、调用Environment.getExternalStorageDirectory()方法来获取外部存储器,也就是SD卡的目录,或者使用"/mnt/sdcard/"目录
3、使用IO流操作SD卡上的文件
注意点:手机应该已插入SD卡,对于模拟器而言,可通过mksdcard命令来创建虚拟存储卡
案例代码:
private voidwrite2(String str, String fileName) {
String filePath = Environment.getExternalStorageDirectory().toString()+ File.separator + "test";
File file = newFile(filePath + File.separator +fileName); // 定义File类对象
if(!file.getParentFile().exists()) { // 父文件夹不存在
file.getParentFile().mkdirs(); // 创建文件夹
}
try {
FileOutputStream out = newFileOutputStream(filePath + File.separator +fileName);
out.write(str.getBytes());
out.close();
Toast.makeText(MainActivity.this, "保存成功",Toast.LENGTH_SHORT).show();
} catch(Exception e) {
// TODOAuto-generated catch block
e.printStackTrace();
}
}
privateString read2(String fileName) {
String filePath = Environment.getExternalStorageDirectory().toString()+ File.separator + "test";
File file = newFile(filePath + File.separator +fileName); // 定义File类对象
try {
FileInputStream in = newFileInputStream(filePath + File.separator +fileName);
int len= in.available();
byte[]temp = new byte[len];
in.read(temp);
String str = EncodingUtils.getString(temp,"UTF-8");
in.close();
return str;
} catch(Exception e) {
// TODOAuto-generated catch block
e.printStackTrace();
return null;
}
}
1.3. Raw目录下文件读取
Android raw目录下的文件读取使用Context提供getResources()函数,获取当前应用资源实例,然后使用openRawResource读取文件,openRawResource的参数是资源的Id标识。
代码例子:
privateString read3(int file) {
String str = "";
try{
InputStream in = getResources().openRawResource(file);
byte[] temp = new byte[in.available()];
//读取数据
in.read(temp);
//依test.txt的编码类型选择合适的编码,如果不调整会乱码
str = EncodingUtils.getString(temp, "BIG5");
//关闭
in.close();
return str;
} catch(Exceptione) {
e.printStackTrace();
return null;
}
}
1.4. Assets目录下文件读取
Assets目录保存的都是保持原始格式的文件,android在编译的时候并不会去编译它们,所以我们不能通过资源Id访问它们,android为我们提供了一个AssetManager类,专门用于应用程序的原始资源文件,在Activity中,可以通过getResources().getAssets()获取AssetManager实例,使用AssetManager的open函数操作文件。
代码例子:
privateString read4(String fileName) {
String str="";
try{
InputStream in =getResources().getAssets().open(fileName);
byte []temp = new byte[in.available()];
in.read(temp);
in.close();
str = EncodingUtils.getString(temp,"UTF-8");
return str;
}catch(Exceptione){
e.printStackTrace();
return null;
}
}
1.5. 使用File类操作文件
File类可以直接处理文件和文件系统,并没有指定信息怎样从文件读取或向文件存储,它主要是完成了文件相关的管理工作,一个File类典型的例子代码:
private void write5(String str,String fileName) {
String filePath = Environment.getExternalStorageDirectory().toString()+ File.separator + "test";
File file = newFile(filePath + File.separator +fileName); // 定义File类对象
if(!file.getParentFile().exists()) { // 父文件夹不存在
file.getParentFile().mkdirs(); // 创建文件夹
}
try {
FileOutputStream out = newFileOutputStream(file);
out.write(str.getBytes());
out.close();
Toast.makeText(MainActivity.this, "保存成功",Toast.LENGTH_SHORT).show();
} catch(Exception e) {
// TODOAuto-generated catch block
e.printStackTrace();
}
}
privateString read5(String fileName) {
String filePath = Environment.getExternalStorageDirectory().toString()+ File.separator + "test";
File file = newFile(filePath + File.separator +fileName); // 定义File类对象
if(!file.getParentFile().exists()) { // 父文件夹不存在
file.getParentFile().mkdirs(); // 创建文件夹
}
try {
FileInputStream in = newFileInputStream(file);
int len= in.available();
byte[]temp = new byte[len];
in.read(temp);
String str = EncodingUtils.getString(temp,"UTF-8");
in.close();
return str;
} catch(Exception e) {
// TODOAuto-generated catch block
e.printStackTrace();
return null;
}
}
下面列举一些File类常用的操作
public boolean delete():删除文件。
public boolean exists():判断文件是否存在。
public String getAbsolutePath():获取文件的绝对路径。
public String getName():获取文件名称。
public String getParent():获取文件所在目录路径。
public String getPath():获取文件的相对路径。
public File getParentFile():获取文件所在目录路径File实例。
public boolean isDirectory():判断该路径指示的是否是文件。
public boolean isFile():判断该路径指示的是否是文件。
public boolean isFile():返回文件长度。
public boolean mkdir():生成指定的目录。
1.6. 使用RandomAccessFile类操作文件
RandomAccessFile的唯一父类是Object,与其他流父类不同。是用来访问那些保存数据记录的文件的,这样你就可以用seek( )方法来访问记录,并进行读写了。这些记录的大小不必相同;但是其大小和位置必须是可知的。
RandomAccessFile是不属于InputStream和OutputStream类系的。实际上,除了实现DataInput和DataOutput接口之外(DataInputStream和DataOutputStream也实现了这两个接口),它和这两个类系毫不相干,甚至都没有用InputStream和OutputStream已经准备好的功能;它是一个完全独立的类,所有方法(绝大多数都只属于它自己)都是从零开始写的。这可能是因为RandomAccessFile能在文件里面前后移动,所以它的行为与其它的I/O类有些根本性的不同。总而言之,它是一个直接继承Object的,独立的类。
代码例子:
private voidwrite6(String str, String fileName) {
String filePath = Environment.getExternalStorageDirectory().toString()+ File.separator + "test";
File file = newFile(filePath + File.separator +fileName); // 定义File类对象
if(!file.getParentFile().exists()) { // 父文件夹不存在
file.getParentFile().mkdirs(); // 创建文件夹
}
file.mkdir();
RandomAccessFile randomFile;
try {
randomFile = newRandomAccessFile(filePath + File.separator +fileName,"rw");
randomFile.write(str.getBytes());
randomFile.close();
Toast.makeText(MainActivity.this, "保存成功",Toast.LENGTH_SHORT).show();
} catch(Exception e) {
// TODOAuto-generated catch block
e.printStackTrace();
}
}
privateString read6(String fileName) {
String filePath = Environment.getExternalStorageDirectory().toString()+ File.separator + "test";
File file = newFile(filePath + File.separator +fileName); // 定义File类对象
if(!file.getParentFile().exists()) { // 父文件夹不存在
file.getParentFile().mkdirs(); // 创建文件夹
}
try {
RandomAccessFile randomFile = newRandomAccessFile(filePath + File.separator +fileName,"rw");
int len= (int)randomFile.length();//取得文件长度(字节数)
byte[]temp = new byte[len];
randomFile.read(temp);
String str = EncodingUtils.getString(temp,"UTF-8");
randomFile.close();
return str;
} catch(Exception e) {
// TODOAuto-generated catch block
e.printStackTrace();
return null;
}
}
1.7. 读取文件时实现类似seek的方式
使用FileInputStream和InputStream可以实现文件的随机读取,FileInputStream提供了一下两个函数
public long skip (long byteCount); //跳过byteCount个字节
public int read (byte[] buffer, int offset,int length); //从数据流中读取length数据存,offset代表buffer的偏移位置。
使用这两个函数来实现文件的随机读取,类似于seek的操作。注意skip和read函数始终是相对于当前位置的。
测试代码:
private voidwriteSeek(String str, String fileName) {
String filePath = Environment.getExternalStorageDirectory().toString()+ File.separator + "test";
File file = newFile(filePath + File.separator +fileName); // 定义File类对象
System.out.println("--------->parent path: " + file.getParent());
if(!file.getParentFile().exists()) { // 父文件夹不存在
file.getParentFile().mkdirs(); // 创建文件夹
}
try {
FileOutputStream out = newFileOutputStream(filePath + File.separator +fileName);
out.write(str.getBytes());
out.close();
Toast.makeText(MainActivity.this, "保存成功",Toast.LENGTH_SHORT).show();
} catch(Exception e) {
// TODOAuto-generated catch block
e.printStackTrace();
}
}
privateString readSeek(String fileName) {
String filePath = Environment.getExternalStorageDirectory().toString()+ File.separator + "test";
File file = newFile(filePath + File.separator +fileName); // 定义File类对象
if(!file.getParentFile().exists()) { // 父文件夹不存在
file.getParentFile().mkdirs(); // 创建文件夹
}
try {
FileInputStream in = newFileInputStream(filePath + File.separator +fileName);
int len= in.available();
byte[]temp = new byte[len];
in.skip(3);
in.read(temp, 0, 3);
String str = EncodingUtils.getString(temp,"UTF-8");
in.close();
return str;
} catch(Exception e) {
// TODOAuto-generated catch block
e.printStackTrace();
return null;
}
}