android文件存储

511人阅读 评论(0) 收藏 举报
分类:

所有的Android设备均有两个文件存储区域:”internal” 与 “external” 。 这两个名称来自于早先的Android系统,当时大多设备都内置了不可变的内存(internal storage)及一个类似于SD card(external storage)这样的可卸载的存储部件。之后有一些设备将”internal” 与 “external” 都做成了不可卸载的内置存储,虽然如此,但是这一整块还是从逻辑上有被划分为”internal”与”external”的。只是现在不再以是否可卸载进行区分了。


两者的区别:

Internal storage
- 总是可用的
- 这里的文件默认只能被我们的app所访问。
- 当用户卸载app的时候,系统会把internal内该app相关的文件都清除干净。
- Internal是我们在想确保不被用户与其他app所访问的最佳存储区域。

External storage
- 并不总是可用的,因为用户有时会通过USB存储模式挂载外部存储器,当取下挂载的这部分后,就无法对其进行访问了。
- 是大家都可以访问的,因此保存在这里的文件可能被其他程序访问。
- 当用户卸载我们的app时,系统仅仅会删除external根目录(getExternalFilesDir())下的相关文件。
- External是在不需要严格的访问权限并且希望这些文件能够被其他app所共享或者是允许用户通过电脑访问时的最佳存储区域。

Note:尽管app是默认被安装到internal storage的,我们还是可以通过在程序的manifest文件中声明android:installLocation 属性来指定程序安装到external storage。当某个程序的安装文件很大且用户的external storage空间大于internal storage时,用户会倾向于将该程序安装到external storage。

对于android的存储,其实就是使用java对文件进行存储或读取

内存存储

当保存文件到internal storage时,可以通过执行下面两个方法之一来获取合适的目录作为 FILE 的对象:
- getFilesDir() : 返回一个File,代表了我们app的internal目录。
- getCacheDir() : 返回一个File,代表了我们app的internal缓存目录。请确保这个目录下的文件能够在一旦不再需要的时候马上被删除,并对其大小进行合理限制,例如1MB 。系统的内部存储空间不够时,会自行选择删除缓存文件

可以使用File() 构造器在那些目录下创建一个新的文件,然后进行存储;同样,也可以执行openFileOutput() 获取一个 FileOutputStream 用于写文件到internal目录。

向内部存储中写内容:

    //文件默认会存储到/data/data/package/files中;
    private void write2FileMethod1(String data, int mode) {
        FileOutputStream outputStream;
        try {
            outputStream = openFileOutput(FILE_NAME, mode);
            outputStream.write(data.getBytes("UTF-8"));
            outputStream.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private void write2FileMethod2(String data) {
        FileOutputStream outputStream;
        try {
            outputStream = new FileOutputStream(getFile());
            outputStream.write(data.getBytes());
            outputStream.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

   private File getFile() {
        return new File(this.getFilesDir(), FILE_NAME);
    }

从内部存储中读取内容

    private void readFromFile() {
        FileInputStream in;
        ByteArrayOutputStream bout;
        byte[]buf = new byte[1024];
        bout = new ByteArrayOutputStream();
        int length;
        try {
            in = this.openFileInput(FILE_NAME);
            while((length = in.read(buf))!=-1){
                bout.write(buf,0,length);
            }
            byte[] content = bout.toByteArray();
            mDataTv.setText(new String(content,"UTF-8"));
            in.close();
            bout.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

外部存储

为确保外置存储可用,我们一般会进行判断:

/* Checks if external storage is available for read and write */
public boolean isExternalStorageWritable() {
    String state = Environment.getExternalStorageState();
    if (Environment.MEDIA_MOUNTED.equals(state)) {
        return true;
    }
    return false;
}

/* Checks if external storage is available to at least read */
public boolean isExternalStorageReadable() {
    String state = Environment.getExternalStorageState();
    if (Environment.MEDIA_MOUNTED.equals(state) ||
        Environment.MEDIA_MOUNTED_READ_ONLY.equals(state)) {
        return true;
    }
    return false;
}

有的手机会有外置存储和内置存储的区分,即手机自带的外置存储和扩展的外置存储的分别,这可以通过某些方法来区分。

尽管external storage对于用户与其他app是可修改的,我们可能会保存下面两种类型的文件。
- Public files :这些文件对与用户与其他app来说是public的,当用户卸载我们的app时,这些文件应该保留。例如,那些被我们的app拍摄的图片或者下载的文件。
- Private files: 这些文件完全被我们的app所私有,它们应该在app被卸载时删除。尽管由于存储在external storage,那些文件从技术上而言可以被用户与其他app所访问,但实际上那些文件对于其他app没有任何意义。因此,当用户卸载我们的app时,系统会删除其下的private目录。例如,那些被我们的app下载的缓存文件。

想要将文件以public形式保存在external storage中,请使用getExternalStoragePublicDirectory()方法来获取一个 File 对象,该对象表示存储在external storage的目录。这个方法会需要带有一个特定的参数来指定这些public的文件类型,以便于与其他public文件进行分类。参数类型包括DIRECTORY_MUSIC 或者 DIRECTORY_PICTURES. 如下:

public File getAlbumStorageDir(String albumName) {
    // Get the directory for the user's public pictures directory.
    File file = new File(Environment.getExternalStoragePublicDirectory(
            Environment.DIRECTORY_PICTURES), albumName);
    if (!file.mkdirs()) {
        Log.e(LOG_TAG, "Directory not created");
    }
    return file;
}

想要将文件以private形式保存在external storage中,可以通过执行getExternalFilesDir() 来获取相应的目录,并且传递一个指示文件类型的参数。每一个以这种方式创建的目录都会被添加到external storage封装我们app目录下的参数文件夹下(如下则是albumName)。这下面的文件会在用户卸载我们的app时被系统删除。如下示例:

public File getAlbumStorageDir(Context context, String albumName) {
    // Get the directory for the app's private pictures directory.
    File file = new File(context.getExternalFilesDir(
            Environment.DIRECTORY_PICTURES), albumName);
    if (!file.mkdirs()) {
        Log.e(LOG_TAG, "Directory not created");
    }
    return file;
}

如果刚开始的时候,没有预定义的子目录存放我们的文件,可以在 getExternalFilesDir()方法中传递null. 它会返回app在external storage下的private的根目录。

getExternalFilesDir() 方法会创建的目录会在app被卸载时被系统删除。如果我们的文件想在app被删除时仍然保留,请使用getExternalStoragePublicDirectory()

    /**
     * 如果想更换存储路径请更换
     * @param childFile
     * @return
     */
    private File getFile(String childFile) {
        return new File(getExternalFilesDir(childFile), FILE_NAME);
    }
    private void write2File(String fileName, String data, boolean isAppend) {
        try {
            FileOutputStream outputStream = new FileOutputStream(getFile(fileName), isAppend);
            outputStream.write(data.getBytes());
            outputStream.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private void readFromFile(String fileName) {
        if(!isExternalStorageReadAble()) {
            showToast("外置存储不可读");
            return;
        }
        ByteArrayOutputStream outputStream;
        byte[] buf = new byte[1024];
        outputStream = new ByteArrayOutputStream();
        int length;
        try {
            FileInputStream inputStream = new FileInputStream(getFile(fileName));
            while ((length = inputStream.read(buf)) != -1) {
                outputStream.write(buf, 0, length);
            }
            byte[] content = outputStream.toByteArray();
            mDataTv.setText(new String(content, "utf-8"));
            outputStream.close();
            inputStream.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

默认情况下,上述写内容的时候是MODE_PRIVATE的,如果想要使用APPEND模式使用下方几种方式:

/**
     * 追加文件:使用FileOutputStream,在构造FileOutputStream时,把第二个参数设为true
     */
    public static void method1(String file, String conent) {
        BufferedWriter out = null;
        try {
            out = new BufferedWriter(new OutputStreamWriter(
                new FileOutputStream(file, true)));
            out.write(conent);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                out.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    /**
     * 追加文件:使用FileWriter
     *
     * @param fileName
     * @param content
     */
    public static void method2(String fileName, String content) {
        try {
            // 打开一个写文件器,构造函数中的第二个参数true表示以追加形式写文件
            FileWriter writer = new FileWriter(fileName, true);
            writer.write(content);
            writer.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    /**
     * 追加文件:使用RandomAccessFile
     *
     * @param fileName
     *            文件名
     * @param content
     *            追加的内容
     */
    public static void method3(String fileName, String content) {
        try {
            // 打开一个随机访问文件流,按读写方式
            RandomAccessFile randomFile = new RandomAccessFile(fileName, "rw");
            // 文件长度,字节数
            long fileLength = randomFile.length();
            // 将写文件指针移到文件尾。
            randomFile.seek(fileLength);
            randomFile.writeBytes(content);
            randomFile.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

可以看出,其实读或写内存或外存的内容不过是将文件的路径改变了而已。

关于删除文件

在不需要使用某些文件的时候应删除它。删除文件最直接的方法是直接执行文件的delete()方法。
myFile.delete();
保存在内部存储中的文件,也可以使用deleteFleece(fileName)来删除:
myContext.deleteFile(fileName);

Note: 当用户卸载我们的app时,android系统会删除以下文件:
- 所有保存到internal storage的文件。
- 所有使用getExternalFilesDir()方式保存在external storage的文件。
然而,通常来说,我们应该手动删除所有通过 getCacheDir() 方式创建的缓存文件,以及那些不会再用到的文件。

具体demo在项目中storage包名下

查看评论

android 文件存储

  • 2013年01月09日 08:02
  • 1.59MB
  • 下载

Android中数据存储——文件存储数据

当一个应用程序在Android中安装后,我们在使用应用的过程中会产生很多的数据,应用都有自己的数据,那么我们应该如何存储数据呢? 数据存储方式Android 的数据存储有5种方式:1. SharedP...
  • To_be_Designer
  • To_be_Designer
  • 2015-09-07 21:35:33
  • 1944

Android 记录一个好用的文件存储操作工具类SDCardHelper

一个Android的文件操作工具类
  • alanjet
  • alanjet
  • 2017-03-03 19:15:53
  • 302

Android的文件存储,文件流简单介绍

1.首先写文件输入输出,那么我们对流要有简单的认识,这里我对流简单向大家解析下2.写文件存储,我们有两种方式获取到文件流对象new FileOutput(file,mode); context.o...
  • qq_34749201
  • qq_34749201
  • 2016-04-22 18:09:42
  • 734

android中的文件存储操作总结

作为android新手,前一段写个程序,想缓存一些数据到android设备中,不知往哪里存,通过查资料总结了一下,以便加深记忆和以后查询,水平有限又是第一次在csdn上写文章,如果不正确的地方,欢迎指...
  • hanyingjie327
  • hanyingjie327
  • 2014-02-13 14:27:11
  • 4857

Android入门:File文件存储

数据的存储有多种方式,比如数据库存储、SharedPreferences存储、文件存储等; 这里我们将要介绍最简单的文件存储方式; 文件存储简单的来说就是一般的JAVASE中的IO流,只是把他应用...
  • xiazdong
  • xiazdong
  • 2012-06-24 15:32:33
  • 50191

简单Demo让你分分钟理解Android中的文件存储

前言 首先,Android中的存储方式有很多种,各自的使用方式以及优点也是不同的,今天写一个简单的Demo来理解一下文件存储。 文件存储:Android中最基本的一种数据存储方式,这种存储...
  • tiankongcheng6
  • tiankongcheng6
  • 2017-01-24 14:32:25
  • 423

Android本地数据存储之文件存储读写

  • 2015年10月27日 15:54
  • 80KB
  • 下载

Android的文件存储

  • 2016年11月16日 12:08
  • 8.56MB
  • 下载

Android XMl文件存储及其解析

Android XMl文件存储及其解析在Android中有许多数据要以文件的形式保存到本地,那么怎么以xml格式的形式来保存文件呢?使用StringBuffer拼接字符串(不推荐)因为demo过于简单...
  • FlyRabbit_1
  • FlyRabbit_1
  • 2017-05-18 14:11:15
  • 347
    个人资料
    持之以恒
    等级:
    访问量: 1万+
    积分: 536
    排名: 9万+
    最新评论