Android 文件数据储存之内部储存 + 外部储存

Android 文件数据储存之内部储存 + 外部储存

内部储存

Android官方API:在设备内存中存储私有数据。

内部储存:Android的内部储存位于系统中,是在手机内存中的文件,!!!不是SD卡(外部存储器)中的文件。内部储存文件默认的存放位置是data/data/files目录下,并且是私有的(private)。可以把它设置为公有的(public),则可以被其他的App访问。当一个应用卸载后,内部储存中的文件会被删除。

使用:内部储存空间十分有限,主要存放系统本身和系统应用的程序的数据,如SharedPreferences,SQLite数据库,普通应用应该尽量避免使用它。

下面主要了解3个文件夹:

核心原理:

Context提供了两个方法来打开数据文件里的文件IO流 FileInputStream openFileInput(String name)与 FileOutputStream(String name , int mode),这两个方法第一个参数 用于指定文件名,第二个参数指定打开文件的模式。具体有以下值可选:

MODE_PRIVATE:默认操作模式,表示该文件为私有数据,只能被应用本身访问,在此模式下,写入的内容会覆盖原文件的内容,如果想把新写入的内容追加到原文件中。可 以使用Context.MODE_APPEND

MODE_APPEND:该模式比较人性化,它会检查文件是否存在,存在就往文件追加内容,否则就创建新文件。

MODE_WORLD_READABLE:当前文件可被其他应用读取。!!

MODE_WORLD_WRITEABLE:当前文件可被其他应用写入。!!

!!官方API提示:自 API 级别 17 以来,常量 MODE_WORLD_READABLE 和 MODE_WORLD_WRITEABLE 已被弃用。从 Android N 开始,使用这些常量将会导致引发 SecurityException。这意味着,面向 Android N 和更高版本的应用无法按名称共享私有文件,尝试共享“file://”URI 将会导致引发 FileUriExposedException。 如果您的应用需要与其他应用共享私有文件,则可以将 FileProvider 与 FLAG_GRANT_READ_URI_PERMISSION 配合使用。

下面介绍一下data文件夹:

打开data文件夹(没有root的手机不能打开该文件夹),里边会有两个文件夹。

(1)app文件夹,存放着所有安装的App的Apk文件。

(2)data文件夹(内部存储),包括以下内容。

data/data/包名/shared_prefs:使用Sharedpreferenced将数据持久化存储于本地,存在这个文件夹中的xml文件里。

data/data/包名/databases:App里的数据库文件

data/data/包名/files:普通数据

data/data/包名/cache:缓存文件,手机内存不足时,会自动删除这里的数据。

Android系统提供了设备内部存储文件的读写操作API,完成文件的创建、内容的读出和写入(包括添加\修改)等。

读取一个内部存储的私有文件的步骤如下。

(1)调用openFilelnput(String filename),参数中填入文件名,会返回一个FileInputstream对象。

(2)使用FileInputstream流对象的read()方法读取字节。

(3)调用流的close()方法关闭流。

写入内部存储文件需要先获得一个文件的输出流,然后以write()的方式把待写入的信息写入到这个输出流中,最后关闭流。具体步骤如下。

(1)使用Context.openFileOutput(string name,int mode)方法,填入文件名和操作模式,获取FileOutputStream 对象.

(2)把待写入的内容通过write()方法写入到FileOutputStream 对象中。

(3)使用FileOutputStream 对象的close()关闭流。

其他文件操作方法如下。

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

File getFilesDir():获本文件系统的绝对路径。

String[] fileList():当前应用内部存储路径下的所有文件名。

boolean deleteFile(String name)删除一个指定文件名为name的文件。

File getDir():在内部存储空间中创建或打开一个已经存在的目录。

下面主要介绍一下文件主要操作类的方法

!!!在调用当前对象的Context后:

1. 保存内容到内部储存器中

可复制代码:

//保存内容到内部服务器中

public void save(String filename, String content)throws IOException{

//FileoutputStream myfos=context.openFileoutput(filename,Context.MODE_PRIVATE);

File file= new File(context.getFilesDir(), filename);

FileOutputStream myfos= new FileOutputStream(file);

myfos.write(content.getBytes());

myfos.close();

}

2. 通过文件名来获取内容

可复制代码:

/**

* 通过文件名来获取内容

* @param filename 文件名称

* @return 文件内容

*/

public String get(String filename) throws IOException {

FileInputStream fis = context.openFileInput(filename);

ByteArrayOutputStream baos = new ByteArrayOutputStream();

byte[] data = new byte[1024];

int len = -1;

while ((len = fis.read(data)) != -1) {

baos.write(data, 0, len);

}

return new String(baos.toByteArray());

}

3.使用追加的方式在文件的末尾添加内容

可复制代码:

/**

* 使用追加的方式在文件的末尾添加内容

* @param filename 文件名

*@param content 追加的内容

*/

public void append(String filename, String content) throws IOException{

FileOutputStream myfos= context.openFileOutput(filename, Context.MODE_APPEND);

myfos.write(content.getBytes());

myfos.close();

}

4.删除文件

可复制代码:

/**

*删除文件

* @param filename 文件名

* @return 是否成功

*/

public boolean delete(String filename) {

return context.deleteFile(filename);

}

5.获取内部存储路径下的所有文件名

可复制代码:

/**

* 获取内部存储路径下的所有文件名

*@return 文件名数组

*/

public String [] queryAllfile(){

return context.fileList();

}

Java文件如下:

public class Internalstorage {

private Context context;

public Internalstorage(Context context) {

this.context = context;

}

//保存内容到内部服务器中

public void save(String filename, String content)throws IOException{

//FileoutputStream myfos=context.openFileoutput(filename,Context.MODE_PRIVATE);

File file= new File(context.getFilesDir(), filename);

FileOutputStream myfos= new FileOutputStream(file);

myfos.write(content.getBytes());

myfos.close();

}

/**

* 通过文件名来获取内容

* @param filename 文件名称

* @return 文件内容

*/

public String get(String filename) throws IOException {

FileInputStream fis = context.openFileInput(filename);

ByteArrayOutputStream baos = new ByteArrayOutputStream();

byte[] data = new byte[1024];

int len = -1;

while ((len = fis.read(data)) != -1) {

baos.write(data, 0, len);

}

return new String(baos.toByteArray());

}

/**

* 使用追加的方式在文件的末尾添加内容

* @param filename 文件名

*@param content 追加的内容

*/

public void append(String filename, String content) throws IOException{

FileOutputStream myfos= context.openFileOutput(filename, Context.MODE_APPEND);

myfos.write(content.getBytes());

myfos.close();

}

/**

*删除文件

* @param filename 文件名

* @return 是否成功

*/

public boolean delete(String filename) {

return context.deleteFile(filename);

}

/**

* 获取内部存储路径下的所有文件名

*@return 文件名数组

*/

public String [] queryAllfile(){

return context.fileList();

}

}

外部储存

Android官方Api:每个兼容 Android 的设备都支持可用于保存文件的共享“外部存储”。 该存储可能是可移除的存储介质(例如 SD 卡)或内部(不可移除)存储。 保存到外部存储的文件是全局可读取文件,而且,在计算机上启用 USB 大容量存储以传输文件后,可由用户修改这些文件。

详解: 外部存储中的文件可以被用户或者其他应用程序读写的,其中有两种类型的文件。

(1).公共文件public fies这类文件可被自由访问,当应用被卸载之后,文件仍然保留。比如相机类应用被卸载后,照片仍然存在。公共文件有9大类,均为系统创建的文件夹,详细如下:

文件夹类型包括:

DCIM : 数字相机拍摄的照片

Music:用户音乐

Podcasts:音频/视频的剪辑片段

Ringtones:铃声

Alarms:闹钟的声音

Notification:通知

Pictures:所有的图片(不包括那些用照相机拍摄的照片)

Movies:所有的电影(不包括那些用摄像机拍摄的视频)和Download/其他下载的内容。

使用外部存储数据需要在应用程序中设置访问SD卡的权限,在AndroidManifest.xml中添加权限

首先判断是否存在可用的SD卡,Environment.getExternalStorageState()方法获取当前设备的状

态,判断是否为Environment.MEDIA_MOUNTED状态。

//判断SD卡是否存在

if(Environment.getExternalStorageState().equals(

Environment.MEDIA_MOUNTED)){

//记得最后要调用保存文件的方法实现保存

Toast.makeText(getApplicationContext(),"sd卡存在",Toast.LENGTH_LONG).show();

}else{

Toast.makeText(getApplicationContext(), "sd卡不存在", Toast.LENGTH_LONG).show();

}

存储的文件路径使用Environment.getExternalStorageDirectory()方法获取当SD卡的根目录,进而访问相应的文件。创建公有文件的方法 :

File file=new File(Environment.getExternalStorageDirectory(),“boreseven”);

第二个参数为自己设置的名字

(2).私有文件Private files在应用被卸载后,私有文件也会被删除,类似与内部储存。获得外部储存私有文件路径的方法Context.getExternalFilesDir(),如:

如:File file = new File(this.getExternalFilesDir(Environment.DIRECTORY_PICTURES), “boreseven”);

下面小提一下两个方法:

1.保存文件到SD卡:

//保存文件到SD卡

public void saveToSDCard(String filename,String content){

File file=new File(Environment.getExternalStorageDirectory(),filename);

try {

FileOutputStream outputStream=new FileOutputStream(file);

outputStream.write(content.getBytes());

outputStream.close();

} catch (FileNotFoundException e) {

e.printStackTrace();

} catch (IOException e) {

e.printStackTrace();

}

}

2.读取SD卡文件:

//读取SD卡文件

public String readFileSdcard(String filename){

String res="";

try {

FileInputStream myfin=new FileInputStream(filename);

int length=myfin.available();

byte [] buff=new byte[length];

myfin.read(buff);

res= new String(buff, "UTF-8");

} catch (FileNotFoundException e) {

e.printStackTrace();

} catch (IOException e) {

e.printStackTrace();

}

return res;

}

拓展:点击按钮下载图片,可在系统相册中显示。

记得要添加权限,代码如下:

xml文件:

xmlns:app="http://schemas.android.com/apk/res-auto"

xmlns:tools="http://schemas.android.com/tools"

android:layout_width="match_parent"

android:layout_height="match_parent"

tools:context=".MainActivity"

>

android:id="@+id/imageView"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:layout_centerInParent="true"

/>

android:id="@+id/mybutton"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:layout_alignParentBottom="true"

android:layout_centerHorizontal="true"

android:text="保存" />

java文件:

public class MainActivity extends Activity {

private ImageView imageView;

private Button mybutton;

private Handler handler;

private String URL="https://www.baidu.com/img/bd_logo1.png";//百度首页图片地址

@Override

protected void onCreate(final Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

initView();

handler=new Handler(new Handler.Callback() {

@Override

public boolean handleMessage(Message msg) {

switch (msg.what){

case 1://成功

byte[]result= (byte[]) msg.obj;

final Bitmap bitmap=BitmapFactory.decodeByteArray(result,0,result.length);//利用BitmapFactory将数据转换成bitmap类型

imageView.setImageBitmap(bitmap);//加载图片

imageView.setOnLongClickListener(new View.OnLongClickListener() {

@Override

public boolean onLongClick(View v) {

saveImageToGallery(MainActivity.this,bitmap);

return false;

}

});

}

return false;

}

});

OkHttpClient client=new OkHttpClient();//实例化

final Request request = new Request.Builder().url(URL).build(); //传入图片网址,,URL为自己定义好的网址。

client.newCall(request).enqueue(new Callback() {//实例化一个call的对象

@Override

public void onFailure(Call call, IOException e) {

}

@Override

public void onResponse(Call call, Response response) throws IOException {

Message message=handler.obtainMessage();//声明一个传递信息的Message

if (response.isSuccessful()){//成功

Log.e("YF", "onResponse: "+"YES" );//一个log,可以不写

message.what=1; //设置成功的指令为1

message.obj=response.body().bytes();//带入图片的数据

handler.sendMessage(message);//将指令和数据传出去

}else{//失败

Log.e("YF", "onResponse: "+"NO" );//一个log,可以不写

handler.sendEmptyMessage(0);//设置其他指令为零,然后进入handler

}

}

});

}

private void saveImageToGallery(Context context, Bitmap bmp) {

// 首先保存图片

File appDir = new File(Environment.getExternalStorageDirectory(),

"desheng");

if (!appDir.exists()) {

appDir.mkdir();

}

String fileName = System.currentTimeMillis() + ".jpg";

File file = new File(appDir, fileName);

try {

FileOutputStream fos = new FileOutputStream(file);

bmp.compress(Bitmap.CompressFormat.JPEG, 100, fos);

fos.flush();

fos.close();

} catch (FileNotFoundException e) {

Toast.makeText(context, "保存失败", Toast.LENGTH_SHORT).show();

e.printStackTrace();

} catch (IOException e) {

Toast.makeText(context, "保存失败", Toast.LENGTH_SHORT).show();

e.printStackTrace();

}

// 其次把文件插入到系统图库

try {

MediaStore.Images.Media.insertImage(context.getContentResolver(),

file.getAbsolutePath(), fileName, null);

Toast.makeText(context, "保存成功", Toast.LENGTH_SHORT).show();

} catch (FileNotFoundException e) {

Toast.makeText(context, "保存失败", Toast.LENGTH_SHORT).show();

e.printStackTrace();

}

// 最后通知图库更新

context.sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE,

Uri.fromFile(new File(file.getPath()))));

}

private void initView() {

imageView = (ImageView) findViewById(R.id.imageView);

mybutton = (Button) findViewById(R.id.mybutton);

}

}

记得加网络权限,图片是加载的百度首页图片!!!

相关推荐

空调抽湿多少时间
365bet足球即时比分

空调抽湿多少时间

📅 07-30 👁️ 6186
《魔兽世界》11.0.7时光漫游新增坐骑一览
365bet客户端

《魔兽世界》11.0.7时光漫游新增坐骑一览

📅 08-05 👁️ 9610
汽配城买配件如何不被坑?
365bet客户端

汽配城买配件如何不被坑?

📅 07-26 👁️ 9133
格力汽车?董明珠造车成功,车标惊艳价格却离谱
365bet足球即时比分

格力汽车?董明珠造车成功,车标惊艳价格却离谱

📅 06-28 👁️ 467
温碧霞演过哪些3级 温碧霞演过的三电影
365不给提款怎么办

温碧霞演过哪些3级 温碧霞演过的三电影

📅 08-04 👁️ 2429
大荒赚钱好项目之捡天珠攻略
365不给提款怎么办

大荒赚钱好项目之捡天珠攻略

📅 07-24 👁️ 4998
欧路词典|英汉-汉英词典 larger是什么意思
365bet客户端

欧路词典|英汉-汉英词典 larger是什么意思

📅 07-06 👁️ 8690
360浏览器插件设置在哪里
365不给提款怎么办

360浏览器插件设置在哪里

📅 08-18 👁️ 4815
诺基亚8.3(8GB/128GB/全网通/5G版)
365bet足球即时比分

诺基亚8.3(8GB/128GB/全网通/5G版)

📅 07-20 👁️ 9097