一、File类

1 、概述

:::tips 而给我们展示出来的并不是二进制数据,而是一个一个的文件,换句话说数据最终都保存在这些文件中。而这些文件又被文件夹管理。 ::: java.io.File 类是文件和目录路径名的抽象表示,主要用于文件和目录的创建、查找和删除等操作。
结论:File类就是描述文件或文件夹的,只要我们在Java中要操作文件或文件夹,就找File类

2 、构造方法

public File(String pathname) 表示根据文件或文件夹的路径名创建一个File对象
public File(String parent, String child) 从父路径名字符串和子路径名字符串创建新的 File实例
public File(File parent, String child) 从父抽象路径名和子路径名字符串创建新的 File实例
注意:一个File对象代表硬盘中实际存在的一个文件或者目录。
无论该路径下是否存在文件或者目录,都不影响File对象的创建。

3、常用方法

获取功能的方法

:::tips public String getAbsolutePath() :获取的当前调用这个方法的File对象的全路径(绝对路径或者真实路径) 返回的是路径的字符串
public String getPath() :获取到当前File类的对象中封装的内容。
public String getName() :获取的是File类的对象中封装的文件或目录的最后一级名称。
public long length() :获取文件大小long size = file.length(); :::

绝对路径和相对路径

:::tips 绝对路径:从盘符开始的路径,这是一个完整的路径。
相对路径:相对于项目目录的路径,这是一个便捷的路径,开发中经常使用。 :::

判断功能的方法

:::tips public boolean exists() :是否存在 如果File类对象中的文件或者文件夹在硬盘上存在 返回 true ,否则返回false;
public boolean isDirectory() :是否是文件夹 如果是文件夹 返回 true 否则返回false;
public boolean isFile() :是否是文件 如果是文件 返回 true , 否则返回false; :::

创建删除功能的方法

:::tips public boolean createNewFile() :当且仅当具有该名称的文件尚不存在时,创建一个新的空文件。
A:true :表示创建文件成功; false :表示创建文件失败,失败原因基本是因为当前的目录有了相同的文件;
B:如果指定的路径不存在,这时就会抛异常 Java.io.IOException:系统找不到指定的路径。这时是不会去创建文件的; :::

4、列举方法

:::tips public String[] list() :返回一个String数组,表示该File目录中的所有子文件或目录。
public File[] listFiles() :返回一个File数组,表示该File目录中的所有的子文件或目录。 ::: 调用listFiles方法的File对象,表示的必须是实际存在的目录,否则返回null,无法进行遍历。

二、IO概述

1 、什么是IO?

:::tips IO技术:它主要的功能就是把我们程序中的数据可以保存到程序以外的其他持久设备中(如:我们电脑的硬盘),或者从其他持久设备中(如:我们电脑的硬盘)进行读取数据,把数据读取到我们的Java程序中 :::

io说明:

:::tips IO:
I:Input:输入或者读取,从持久设备(硬盘)的数据放到内存中;
O:Output:输出或者写出,从内存中的数据放到持久设备(硬盘)上; :::

2 、IO的分类

按流向分:

  • 输入流:读取数据,把持久设备的数据读取到内存中。
  • 输出流:写出数据,把内存的数据写出到持久设备。

    按数据类型分:

    :::tips

  • 字节流:数据在持久设备上都是以二进制形式保存的。二进制就是字节数据。Java就给出了字节流可以直接操作字节数据。 字节输入流:InputStream 儿子:XxxInputStream 字节输出流:OutputStream 儿子:XxxOutputStream

  • 字符流:读取字符数据。数据在设备上是以二进制形式表示,但是有些二进制合并在一起可以表示一些字符数据。 字符输入流:Reader 儿子:XxxReader 字符输出流:Writer 儿子:XxxWriter :::

    4、顶级父类

    | | 输入流 | 输出流 | | —- | —- | —- | | 字节流 | 字节输入流:InputStream | 字节输出流:OutputStream | | 字符流 | 字符输入流:Reader | 字符输出流:Writer |


三、字节流

1、字节输出流【OutputStream】

  • public void close() :关闭此输出流并释放与此流相关联的任何系统资源。
  • public void write(byte[] b):把这个b字节数组中的所有数据写到关联的设备中(设备包括文件、网络或者其他任何地方)。
  • public void write(byte[] b, int off, int len) :把b字节中的数据从下标off位置开始往出写,共计写len个。
  • public abstract void write(int b) : 把这个b数据写到关联的设备中。

close方法,当完成流的操作时,必须调用此方法,释放系统资源。

2、FileOutputStream类

构造方法

  • public FileOutputStream(File file):创建文件输出流以写入由指定的 File对象表示的文件。
  • public FileOutputStream(String name): 创建文件输出流以指定的名称写入文件。

    数据追加续写

  • public FileOutputStream(File file, boolean append): 创建文件输出流以写入由指定的 File对象表示的文件。

  • public FileOutputStream(String name, boolean append): 创建文件输出流以指定的名称写入文件。

    3、字节输入流【InputStream】

  • public void close() :关闭此输入流并释放与此流相关联的任何系统资源。

  • public abstract int read(): 调用一次read,就可以从关联的文件中读取一个字节数据,并返回这个字节数据。方法可以从关联的文件中读取数据。所有read方法如果读取到文件的末尾,都会返回-1。遇到-1就代表文件中的数据已经被读取完毕。
  • public int read(byte[] b): 调用一次,读取多个字节数据,把读到的字节数据保存在传递的b字节数组中。返回字节数组中读取的字节个数。注意啦:这个返回值不是数组长度。

close方法,当完成流的操作时,必须调用此方法,释放系统资源。

构造方法

  • FileInputStream(File file): 通过打开与实际文件的连接来创建一个 FileInputStream ,该文件由文件系统中的 File对象 file命名。
  • FileInputStream(String name): 通过打开与实际文件的连接来创建一个 FileInputStream ,该文件由文件系统中的路径名 name命名。

    多字节读取

    1. //定义一个数组
    2. // byte[] b=new byte[5];
    3. //终极版代码模板
    4. byte[] b=new byte[1024];//数组长度一般是1024的整数倍
    5. //定义一个变量保存读取字节的个数
    6. int len=0;
    7. //fis.read(b)表示读取的数据都存放到byte数组中了,len表示读取字节数
    8. while((len=fis.read(b))!=-1)//一定要传递参数数组b
    9. {
    10. System.out.print(new String(b,0,len));
    11. }
    12. //关闭资源
    13. fis.close();

    四、属性集

    1 概述

    java.util.Properties 继承于Hashtable ,来表示一个持久的属性集。它使用键值结构存储数据,每个键及其对应值都是一个字符串。

    1 概述

    java.util.Properties 继承于Hashtable ,来表示一个持久的属性集。它使用键值结构存储数据,每个键及其对应值都是一个字符串。

    构造方法

  • public Properties() :创建一个空的属性列表。

    基本的存储方法

  • public Object setProperty(String key, String value) : 保存一对属性。 等同于Map中的put功能

  • public String getProperty(String key) :使用此属性列表中指定的键搜索属性值。等同于Map中的 get(Object key)
  • public Set stringPropertyNames() :所有键的名称的集合。等同于Map中的keySet方法

    与流相关的方法

  • public void load(InputStream inStream): 从字节输入流中读取键值对。

    public class ProDemo2 {
      public static void main(String[] args) throws FileNotFoundException {
          //创建集合对象
          Properties prop = new Properties();
          //使用集合对象prop调用load()函数从硬盘上加载数据
    //        prop.load(new FileInputStream("D:\\person.txt"));
          prop.load(new FileReader("D:\\person.txt"));
          //遍历集合
          Set<String> keys = prop.stringPropertyNames();
          for (Iterator<String> it = keys.iterator(); it.hasNext();) {
              String key = it.next();
              //根据key键获得value
              String value = prop.getProperty(key);
              System.out.println(key+"---"+value);
            }
       }
    }
    

    注意:文本中的数据,必须是键值对形式。

    五、ResourceBundle工具类

    1、创建对象

    :::tips // 使用指定的基本名称,默认语言环境和调用者的类加载器获取资源包。
    static ResourceBundle getBundle(String baseName); 参数:baseName:给定参数只需要配置文件的名称,不要扩展名。 :::

    2、获取方法

    ResourceBundle类提供了一个getString(String key)方法用于读取配置文件中指定key的值
    String getString(String key) //根据键获取值

    六、递归

    :::tips 递归调用的细节:必须要求递归中有可以让函数调用的结束条件。否则函数一直调用,就会导致内存溢出。想 ::: 案例:求菜单的权限树包含1级2级3级和按钮菜单
    image.png

    /**
       * @param permissions 权限树状集合
       * @param pid 权限父id,顶级权限的pid默认为0
       * @param isOnlyMenuType true:遍历到菜单,  false:遍历到按钮
       * type: 目录1 菜单2 按钮3
       * @return
       */
      @Override
      public List<PermissionRespNodeVo> getTree(List<SysPermission> permissions,String pid,boolean isOnlyMenuType) {
          ArrayList<PermissionRespNodeVo> list = Lists.newArrayList();
          if (CollectionUtils.isEmpty(permissions)) {
              return list;
          }
          for (SysPermission permission : permissions) {
              if (permission.getPid().equals(pid)) {
                  if (permission.getType().intValue()!=3 || !isOnlyMenuType) {
                      PermissionRespNodeVo respNodeVo = new PermissionRespNodeVo();
                      respNodeVo.setId(permission.getId());
                      respNodeVo.setTitle(permission.getTitle());
                      respNodeVo.setIcon(permission.getIcon());
                      respNodeVo.setPath(permission.getUrl());
                      respNodeVo.setName(permission.getName());
                      respNodeVo.setChildren(getTree(permissions,permission.getId(),isOnlyMenuType));
                      list.add(respNodeVo);
                  }
              }
          }
          return list;
      }
    

    案例:在你的计算机某一个盘的根目录创建一个文件夹做测试用,里面放置一些含有子文件的文件夹,及一些文件。写程序实现删除非空文件夹。 ```java

package com.itheima.work;
import java.io.File;

//在你的计算机某一个盘的根目录创建一个文件夹做测试用,里面放置一些含有子文件的文件夹,及一些文件。写程序实现删除非空文件夹。
//
//代码模板
public class streamTest03 {
    public static void main(String[] args) {

        removeFile(new File("E:\\统计文件个数文件夹.jpg"));
    }

    public static void removeFile(File dir) {
        //TODO 实现删除文件夹
        if (dir.isDirectory()) {
            for (File file : dir.listFiles()) {
                if (file.isFile()) {
                    file.delete();
                } else {//判断文件夹是否为非空文件夹
                    if (file.length() != 0) {
                        removeFile(file);
                    }
                }
            }
        }
    }
}
案例:求阶乘
```java
package cn.itcast.sh.digui.demo;
/*
 * 方式2:使用递归思想来解决5的阶乘
 *方式一: 5!=5*4*3*2*1;
 *方式二:5!=5*4!
 *              4!=4*3!
 *                    3!=3*2!
 *                          2!=2*1!
 *                                1!=1*0!
 *找规律:n!=n*(n-1)!
 *找结束条件:
 *    if(n<=1) return 1;
 */
public class DiGuiDemo3 {
    public static void main(String[] args) {
        // 调用函数求5的阶乘
        int result=jc2(5);
        System.out.println(result);//120
    }
    //自定义函数求5的阶乘
    public static int jc2(int n) {
        // 结束条件
        if(n<=1)
        {
            return 1;
        }
        return n*jc2(n-1);
    }
}

递归注意事项

递归必须有结束条件,否则栈内存会溢出,称为死递归!栈炸了。 image.png image.png