Java 基础(十一)File 操作及自定义MySharedPreferences

908 阅读7分钟

File 概述

我们先来看看 File 类的定义

File :文件和目录路径名的抽象表示形式。

嗯~ File 可以用来表示一个文件及其路径等相关信息。
文件夹是一个特殊的文件。

好吧,不瞎扯了,大家都知道 File 是用来表示文件就行了,我们来看看 API

方法名 方法描述
canExecute() 测试应用程序是否可执行此抽象路径名表示的文件
canRead() 测试应用程序是否可读取此抽象路径名表示的文件
canWrite() 测试应用程序是否可修改此抽象路径名表示的文件
createNewFile() 当且仅当该文件不存在时,创建一个新的空文件
delete() 删除此抽象路径名表示的文件或目录
deleteOnExit() 在虚拟机终止时,请求删除此抽象路径名表示的文件或目录
exists() 测试此抽象路径名表示的文件或目录是否存在
getAbsoluteFile() 返回此抽象路径名的绝对路径名形式
getAbsolutePath() 返回此抽象路径名的绝对路径名字符串
getCanonicalFile() 返回此抽象路径名的规范形式
getCanonicalPath() 返回此抽象路径名的规范路径名字符串
getFreeSpace() 返回此抽象路径名指定的分区中未分配的字节数
getName() 返回由此抽象路径名表示的文件或目录的名称
getParent() 返回此抽象路径名父目录的路径名字符串;如果此路径名没有指定父目录,则返回 null
getParentFile() 返回此抽象路径名父目录的抽象路径名;如果此路径名没有指定父目录,则返回 null
getPath() 将此抽象路径名转换为一个路径名字符串
getTotalSpace() 返回此抽象路径名指定的分区大小
getUsableSpace() 返回此抽象路径名指定的分区上可用于此虚拟机的字节数
isAbsolute() 测试此抽象路径名是否为绝对路径名
isDirectory() 测试此抽象路径名表示的文件是否是一个目录
isFile() 测试此抽象路径名表示的文件是否是一个标准文件
isHidden() 测试此抽象路径名指定的文件是否是一个隐藏文件
lastModified() 返回此抽象路径名表示的文件最后一次被修改的时间
length() 返回由此抽象路径名表示的文件的长度
list() 返回一个字符串数组,这些字符串指定此抽象路径名表示的目录中的文件和目录
list(FilenameFilter filter) 返回一个字符串数组,这些字符串指定此抽象路径名表示的目录中满足指定过滤器的文件和目录
listFiles() 返回一个抽象路径名数组,这些路径名表示此抽象路径名表示的目录中的文件
listFiles(FilenameFilter filter) 返回抽象路径名数组,这些路径名表示此抽象路径名表示的目录中满足指定过滤器的文件和目录
listRoots() 列出可用的文件系统根
mkdir() 创建此抽象路径名指定的目录
mkdirs() 创建此抽象路径名指定的目录,包括所有必需但不存在的父目录
renameTo() 重新命名此抽象路径名表示的文件
setExecutable(boolean executable) 设置此抽象路径名所有者执行权限的一个便捷方法
setLastModified(long time) 设置此抽象路径名指定的文件或目录的最后一次修改时间
setReadable(boolean readable) 设置此抽象路径名所有者读权限的一个便捷方法
setReadOnly() 标记此抽象路径名指定的文件或目录,从而只能对其进行读操作
setWritable(boolean writable) 设置此抽象路径名所有者写权限的一个便捷方法
toURI() 构造一个表示此抽象路径名的 file: URI
toURL() 过时方法,建议使用 file.toURI().toRUL()

File 练习:列出一个文件夹下所有文件名

需求,打印文件里面的所有文件名
思考:文件夹里面所有文件,判断如果是文件就执行打印,如果是文件夹重复上面操作

刚刚我们思考的这种解决问题思路可以用“递归算法”来实现,我们来简单了解一下上面叫递归算法吧。

递归

程序调用自身的编程技巧称为递归( recursion)。递归做为一种算法在程序设计语言中广泛应用。 一个过程或函数在其定义或说明中有直接或间接调用自身的一种方法,它通常把一个大型复杂的问题层层转化为一个与原问题相似的规模较小的问题来求解,递归策略只需少量的程序就可描述出解题过程所需要的多次重复计算,大大地减少了程序的代码量。递归的能力在于用有限的语句来定义对象的无限集合。一般来说,递归需要有边界条件、递归前进段和递归返回段。当边界条件不满足时,递归前进;当边界条件满足时,递归返回。

定义

递归,就是在运行的过程中调用自己

构成递归需具备的条件

  • 子问题必须与原始问题为同样的事,且更为简单;
  • 不能无限制地调用本身,必须有个出口

递归算法一般用于解决以下三类问题:

  • 数据的定义是按递归定义的
  • 问题解法按递归算法实现
  • 数据的结构形式是按递归定义的(如链表、二叉树、广义表等)

递归的缺点:

递归算法解题相对常用的算法如普通循环等,运行效率较低。因此,应尽量避免使用递归,除非没有更好的算法或某种特定情况,递归更为合适的时候。在递归调用的过程当中系统为每一层的返回点、局部量等开辟了栈来存储,递归次数过多容易造成栈溢出等。

递归的代码实现

private static void showDir(File dir) {
    System.out.println("目录:" + dir);
    File[] files = dir.listFiles();
    for (File file : files) {
        if (file.isDirectory()) {
            showDir(file);
        } else {
            // 列出根目录
            System.out.println("files" + file);
        }
    }
}

Properties

额,这是一个我之前没有接触过的类,继承自 HashTable,也就是说它具有 map 集合的特点,而且键值对都是字符串。

它有什么特点?为什么突然在这里又讲集合。。。。

我们来看看 JDK 的描述~

Properties 类表示了一个持久的属性集,Properties 可保存在流中或从流中加载.
因为 Properties 继承于 Hashtable,所以可对 Properties 对象应用 put 和 putAll 方法。但不建议使用这两个方法,因为它们允许调用者插入其键或值不是 String 的项。

我们可以从中读取到几个重要的信息。map 集合、字符串键值对、持久的属性集。
好了,我就不卖关子了,这玩意可以用来设置配置文件。

类似于 SharedPreferences,我们可以自己用Properties 来实现MySharedPreferences呀。

我这里手撸了一个 MySharedPreference,没有经过测试的,大家凑合着看一下,哈哈😀

public class MySharedPreferences {
    private static MySharedPreferences mInstance;
    private final String mPath;

    public static MySharedPreferences getInstance() {
        if (mInstance == null) {
            synchronized (MySharedPreferences.class) {
                if (mInstance == null) {
                    mInstance = new MySharedPreferences();
                }
            }
        }
        return mInstance;
    }

    private MySharedPreferences() {
        mPath = Environment.getExternalStorageDirectory().getPath() + "SP.txt";
        File file = new File(mPath);
        if (!file.exists()) {
            try {
                file.createNewFile();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    public void putValue(String key, String value) {
        try {
            BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter(mPath, true));
            BufferedReader bufferedReader = new BufferedReader(new FileReader(mPath));
            Properties properties = new Properties();
            properties.load(bufferedReader);
            properties.setProperty(key, value);
            properties.store(bufferedWriter, "");
            bufferedWriter.flush();
            bufferedReader.close();
            bufferedWriter.close();
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

    public String getValue(String key) {
        try {
            BufferedReader bufferedReader = new BufferedReader(new FileReader(mPath));
            Properties properties = new Properties();
            properties.load(bufferedReader);

            bufferedReader.close();
            return properties.getProperty(key);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }
}

反正就是酱紫玩的咯,有兴趣的小伙伴可以帮我测试一下 MySharedPreference,记得在 Manifest 文件里面申请读写权限哦。我觉得是不需要申请权限的,懒得去测试了,小伙伴们可以根据自己对 android 的理解,告诉我这需不需要权限。至于性能问题,读写 SP 应该是一件低频率的事情,所以读写流在需要的时候创建,不需要的时候关闭。

IO 流及文件操作的学习就到这里吧~~
NIO 的并发类的操作等以后学并发的时候再一次性扫盲。