File文件可用来存放大量数据,如文本、图片、音频、视频等。
在Android的数据存储操作和Java中的IO流差不多的用法。
进行File数据存储的步骤如下:
①打开一个File对象
②打开一个FileOutputStream文件输出流,写入数据
③打开一个FileInputStream文件输入流,读取数据
我们先要获取File对象,才能打开一个文件输入输出流。
在Android在Context下有一些自带的获取File对象的方法,在这些路径中,里面的文件会随着APP的卸载而删除,不会残留数据垃圾。
File getFilesDir();//获取/data/data/包名/files 的File对象,默认的数据存储目录
File getCacheDir();//获取/data/data/包名/cache 的File对象,默认的缓存文件存储位置,系统会自动删除
File getExternalFilesDir();//获取/mnt/sdcard/Android/data/包名/files 的File对象,默认的外部的数据存储目录
File getExternalCacheDir();//获取/mnt/sdcard/Android/data/包名/cache 的File对象,默认的外部的缓存文件存储位置
File getDir("文件夹名", MODE_PRIVATE);//获取/data/data/包名/app_文件夹名 目录,默认的数据存储目录
而如果不按照上面的方法进行存储数据,想要在自定义的位置存储文件,则在APP卸载后,数据不会自动删除,残留数据垃圾。
并且,我们需要在AndroidManifest.xml里面写入这两个权限,并获取File对象,写入读取数据
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/><!--在SD卡中创建与删除文件的权限-->
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/><!--向SD卡写入数据的权限-->
File file = new File("/mnt/sdcard/test");//new一个File对象,指向/mnt/sdcard/test,不管存不存在
if(file.exists()){//判断File是否存在
file.createNewFile();//不存在的话就新建该文件
}
除了上面的方法外,我们还可以直接使用openFileOutput()和openFileInput()获取文件输出输入流对象
他们指定在/data/data/包名/files目录下新建一个name文件,注意文件最好加上后缀名,如:demo.txt
FileOutputStream fos = openFileOutput(String name, int mode);//name表示文件名
FileInputStream fis = openFileInput(String name);//文件名
mode参数指示打开文件的模式,在之前的SharedPreferences中有介绍过。
这两个过时的权限会造成安全漏洞,有需要的话可以使用ContentProvider来代替。
- MODE_PRIVATE//私有模式,只能被应用本身访问,在该模式下写入的内容会覆盖原文件
- MODE_APPEND//追加模式,存在就往文件追加内容,否则创建新文件
MODE_WORLD_READABLE//只读模式,允许其他应用进行读操作(已过时)MODE_WORLD_WRITEABLE//读写模式,允许其他应用进行读、写操作(已过时)
以下是demo源码
public class MainActivity extends Activity {
Button privateButton,appendButton;
EditText inputEdit;
TextView outputText;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
privateButton = (Button) findViewById(R.id.privateButton);
appendButton = (Button) findViewById(R.id.appendButton);
inputEdit = (EditText) findViewById(R.id.inputEdit);
outputText = (TextView) findViewById(R.id.outputText);
privateButton.setOnClickListener(new View.OnClickListener() {//私有模式
@Override
public void onClick(View view) {
try {
FileOutputStream fos = openFileOutput("test1.txt", MODE_PRIVATE);//以私有模式打开一个test1.txt文件的文件输出流
fos.write(inputEdit.getText().toString().getBytes());//写入数据,记得转换为byte[]类型
fos.close();//关闭文件输出流
FileInputStream fis = openFileInput("test1.txt");//打开一个指向test1.txt的文件输入流
ByteArrayOutputStream baos = new ByteArrayOutputStream();//new 一个缓冲数组输出流对象
byte[] buf = new byte[1024];
int len;
while((len=fis.read(buf)) != -1) {
baos.write(buf, 0, len);//写入缓冲区
}
outputText.setText(baos.toString());//从缓冲区中读取
baos.close();
fis.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
});
appendButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
try {
FileOutputStream fos = openFileOutput("test2.txt", MODE_APPEND);//同上,这次是以追加模式打开
fos.write(inputEdit.getText().toString().getBytes());//文件存储在/data/data/包名/files/test2.txt
fos.close();
FileInputStream fis = openFileInput("test2.txt");
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] buf = new byte[1024];
int len;
while((len=fis.read(buf))!=-1){
baos.write(buf, 0, len);
}
outputText.setText(baos.toString());
baos.close();
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
});
}
}
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<EditText
android:id="@+id/inputEdit"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<Button
android:id="@+id/privateButton"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:text="Private"/>
<Button
android:id="@+id/appendButton"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:text="Append" />
<TextView
android:id="@+id/outputText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="读取内容"/>
</LinearLayout>