Android 文件读写

时间:2023-12-15 12:59:26

一、分类

文件读写作为Android四大数据存储方式之一,又分为内部存储和外部存储两种:

(1)内部存储(Internal storage):

  1. 总是可用。
  2. 文件默认情况存储在/data/data/包名/files,缓存文件存储在/data/data/包名/cache中,默认情况下只能只能被本APP操作,当然可以在openFileOutput()中指定是否可被其他app读写。
  3. 当使用者卸载你的app时,系统会自动从内部存储中删除安排app的所有文件。

(2)外部存储(External storage):

  1.并不是总是可用,因为用户有可能将SD卡作为USB存储挂载或者在某些情况下将SD卡从设备上卸下,因此需要使用getExternalStorageState()来查询外部存储的状态,当返回的状态是MEDIA_MOUNTED时才能读写。

  2.保存在外部存储的文件是world-readable的,所以保存在外部存储的文件可能被其他应用读取。

  3.当用户卸载app时,只用当你调用getExternalFilesDir()来保存文件时系统才会从外部存储中移除app的文件。

  4.权限:

  <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

  向SD卡写入数据权限,隐式授予了读取权限

  <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>

  当app只需要读取而非写入权限的时候更适合使用该权限

  <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>

  在SD卡中创建和删除文件权限

二、方法介绍

  1)getFilesDir():返回/data/data/包名/files

  2)getCacheDir():返回/data/data/包名/cache,在确定缓存文件不再需要时删除掉,为app使用的内存量实现一个合理的大小限制,比如1M。如果系统在存储空间低的时候运行,可能会在没有警告的时候删除缓存文件。

  3)FileInputStream openFileInput(String name):打开应用程序文件夹下的nam文件对应的输入流。

  4)FileOutputStream openFileOutput(String name,int mode):打开应用程序文件夹下的nam文件对应的输出流(若文件不存在则创建),第二个参数指定打开文件的模式:

    MODE_PRIVATE:该文件只能被当前程序读写

    MODE_APPEND:已追加方式打开该文件

    MODE_WORLD_READABLE:该文件可被其他程序读取

    MODE_WORLD_WRITEABLE:该文件可被其他程序读写

  5)getDir(String name,int mode):在应用程序的数据文件夹下获取或创建app_name对应的子目录

    第二个参数:     

    MODE_PRIVATE:默认模式,该文件只能被当前程序访问

    MODE_WORLD_READABLE:该文件可被其他程序访问(在API17被弃用)

    MODE_WORLD_WRITEABLE:该文件可被其他程序读写(在API17被弃用)

  6)String[] fileList():返回应用程序的数据文件夹下的全部文件名

  7)deleteFile(String name):删除应用程序的数据文件夹下指定文件

  8)Environment.getExternalStorageState():判断手机是否插入SD卡,当返回MEDIA_MOUNTED时才能对其进行读写

  9)getExternalStorageDirectory():返回SD卡的根目录  /storage/emulated/0

  10)getExternalStoragePublicDirectory(String type):在SD卡的根目录创建一个由type指定的特定类型的文件夹

  例如:/storage/emulated/0/Pictures

  11)getExternalFilesDir(String type):在SD卡中对应应用的数据文件夹中创建一个由type指定的特定类型的文件夹

  例如:storage/emulated/0/Android/data/应用包名/files/Pictures

  type可选项:

    DIRECTORY_MUSIC 标准音乐目录,

    DIRECTORY_PODCASTS ,

    DIRECTORY_RINGTONES 铃声,

    DIRECTORY_ALARMS 警报音,

    DIRECTORY_NOTIFICATIONS 通知音,

    DIRECTORY_PICTURES 图片,

    DIRECTORY_MOVIES 电影,

      DIRECTORY_DOWNLOADS 下载,

    DIRECTORY_DCIM 由camera拍摄的照片和视频存放目录

  TIPS:(1)需要注意的是getExternalStoragePublicDirectory()与getExternalFilesDir()的区别在于前者所创建的文件不会在用户卸载被系统删除,而后者在SD卡创建的应用程序数据文件会被系统删除。

     (2)当用户卸载APP的时候系统会删除所有在内部存储中对应APP的文件以及由getExternalFilesDir()调用创建的文件。

三、代码示例

内部存储:

import android.content.Context;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText; import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException; public class MainActivity extends AppCompatActivity { final String FILE_NAME="test.txt";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button read= (Button) findViewById(R.id.read);
final Button write= (Button) findViewById(R.id.write);
final EditText editText= (EditText) findViewById(R.id.edit_area);
write.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
write(editText.getText().toString());
editText.setText("");
}
});
read.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
editText.setText(read());
}
});
findViewById(R.id.delete).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
delete(FILE_NAME,MainActivity.this);
}
});
}
private String read(){
try {
FileInputStream fis=openFileInput(FILE_NAME);
byte[] buff=new byte[1024];
int hasRead=0;
StringBuffer sb=new StringBuffer();
while ((hasRead=fis.read(buff))>0){
sb.append(new String(buff,0,hasRead));
}
fis.close();
return sb.toString();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
private void delete(String name,Context context){
context.deleteFile(name);
}
private void write(String content){
try {
FileOutputStream fos=openFileOutput(FILE_NAME,MODE_PRIVATE);
try {
fos.write(content.getBytes());
} catch (IOException e) {
e.printStackTrace();
}
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
}
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
android:layout_height="match_parent" android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:paddingBottom="@dimen/activity_vertical_margin" tools:context=".MainActivity"> <EditText
android:id="@+id/edit_area"
android:lines="5"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<Button
android:id="@+id/read"
android:layout_below="@id/edit_area"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="读入"/>
<Button
android:id="@+id/write"
android:layout_toRightOf="@id/read"
android:layout_below="@id/edit_area"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="写入"/>
<Button
android:id="@+id/delete"
android:layout_below="@id/edit_area"
android:text="删除"
android:layout_toRightOf="@id/write"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</RelativeLayout>

外部存储:

package com.example.administrator.externalfile;

import android.content.Context;
import android.os.Environment;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.EditText; import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.RandomAccessFile; public class MainActivity extends AppCompatActivity { private String TAG="ENTERNAL";
private String FILE_NAME="/test.txt";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Log.d(TAG, "ExternalStoragePublicDir=" + Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES));
Log.d(TAG, "ExternalFilesDir=" + MainActivity.this.getExternalFilesDir(Environment.DIRECTORY_PICTURES));
Log.d(TAG,"ExternalStorageDir="+Environment.getExternalStorageDirectory());
final EditText editText= (EditText) findViewById(R.id.edit_area);
Button read= (Button) findViewById(R.id.read);
final Button write= (Button) findViewById(R.id.write);
read.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
editText.setText(read());
}
});
write.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
write(editText.getText().toString());
editText.setText("");
}
});
}
public boolean isExternalStorageWritable(){
String state= Environment.getExternalStorageState();
if (Environment.MEDIA_MOUNTED.equals(state)){
return true;
}
return false;
}
public boolean isExternalStorageReadable(){
String state=Environment.getExternalStorageState();
if (Environment.MEDIA_MOUNTED.equals(state)||Environment.MEDIA_MOUNTED_READ_ONLY.equals(state)){
return true;
}
return false;
} /**
* 获取外部公用存储路径
* @param albumName
* @return
*/
public File getAlbumStorageDir(String albumName){
File file=new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES),albumName);
if (!file.mkdirs()){
Log.d(TAG,"Directory not create");
}
return file;
} /**
* 获取私有外部存储目录
* @param context
* @param albumName
* @return
*/
public File getAlbumStorageDir(Context context,String albumName){
File file=new File(context.getExternalFilesDir(Environment.DIRECTORY_PICTURES),albumName);
if (!file.mkdirs()){
Log.d(TAG,"Directory not create");
}
return file;
}
private String read(){
if (isExternalStorageWritable()){
// File sdCard=Environment.getExternalStorageDirectory();
File sdCard=getAlbumStorageDir(MainActivity.this,"test");
try {
FileInputStream fis=new FileInputStream(sdCard.getCanonicalPath()+FILE_NAME);
StringBuilder sb=new StringBuilder("");
byte[] buff=new byte[1024];
int hasRead=0;
while ((hasRead=fis.read(buff))!=-1){
sb.append(new String(buff,0,hasRead));
}
return sb.toString();
} catch (IOException e) {
e.printStackTrace();
}
}
return null;
} private void write(String content){
if (isExternalStorageWritable()){
// File sdCard=Environment.getExternalStorageDirectory();
File sdCard=getAlbumStorageDir(MainActivity.this,"test");
try {
File targetFile=new File(sdCard.getCanonicalPath()+FILE_NAME);
RandomAccessFile raf=new RandomAccessFile(targetFile,"rw");
raf.seek(targetFile.length());
raf.write(content.getBytes());
raf.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
android:layout_height="match_parent" android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:paddingBottom="@dimen/activity_vertical_margin" tools:context=".MainActivity"> <EditText
android:id="@+id/edit_area"
android:lines="5"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<Button
android:id="@+id/read"
android:layout_below="@id/edit_area"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="读入"/>
<Button
android:id="@+id/write"
android:layout_toRightOf="@id/read"
android:layout_below="@id/edit_area"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="写入"/>
<Button
android:id="@+id/delete"
android:layout_below="@id/edit_area"
android:text="删除"
android:layout_toRightOf="@id/write"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</RelativeLayout>

参考自:

  http://developer.android.com/training/basics/data-storage/files.html