先要区分两个名词:FileInputStream和FileOutputStream。这两个名词都是相对于应用来说的,而不是相对于文件。
从文件中读取数据时,使用FileInputStream;将数据写入文件中时,使用FileOutputStream。
读取文件数据到byte数组典型做法:
private byte[] readFileToByteArray(String path) {
File file = new File(path);
if(!file.exists()) {
Log.e(TAG,"File doesn't exist!");
return null;
}
try {
FileInputStream in = new FileInputStream(file);
long inSize = in.getChannel().size();//判断FileInputStream中是否有内容
if (inSize == 0) {
Log.d(TAG,"The FileInputStream has no content!");
return null;
}
byte[] buffer = new byte[in.available()];//in.available() 表示要读取的文件中的数据长度
in.read(buffer); //将文件中的数据读到buffer中
return buffer;
} catch (FileNotFoundException e) {
e.printStackTrace();
return null;
} catch (IOException e) {
e.printStackTrace();
return null;
} finally {
try {
in.close();
} catch (IOException e) {
return null;
}
//或IoUtils.closeQuietly(in);
}
}
将读出来的数据写入文件中并强制刷新到文件中:
private void writeAndFlush(String path, byte[] buffer) {
try {
FileOutputStream out = new FileOutputStream(path);//指定写到哪个路径中
FileChannel fileChannel = out.getChannel();
fileChannel.write(ByteBuffer.wrap(buffer)); //将字节流写入文件中
fileChannel.force(true);//强制刷新
fileChannel.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOExceptioin e) {
e.printStackTrace();
}
}
此处使用的FileChannel.force()方法刷新。
应用场景:
Andorid系统的设计中,SettingsProvider的对应文件中,如果某个属性发生改变时,先是修改了缓冲区的数据,并未立即flush到文件中。
而Android系统的设计是每5s会检测一次属性是否发生改变,如有变化就会flush到文件中。
因此,如在设置了音量或亮度后,如果立即重启,重启前后的值是不一致的,因为值还未被flush到文件中。
因此可以在SettingsProvider的SettingsState.java的doWriteState()接口(该接口是修改settings_system.xml等文件的接口)中,增加强制刷新的code,即如上所述,将缓冲区的数据强制刷新到文件中。
这样手动强制刷新的好处是,修改了属性后,值立马保存到了文件中,即便立刻重启,重启前后的值也是一致的。
不能采用修改系统设计的每5s检测一次进行flush的操作,因为若将时间缩短,则频繁flush,IO操作的CPU占用率就会很高。