JavaSE进阶笔记:08(File、方法递归、字符集)

102 阅读7分钟

一、File

1.File概述

  • File类在包java.io.File下,代表操作系统的文件对象(文件、文件夹);
  • 提供:定位文件、获取文件本身信息、删除文件、创建文件(夹)等功能;
/**
 * 创建File对象
 */
public class FileDemo01 {
    public static void main(String[] args) {
        /**
         * 指定文件路径(绝对路径)
         */
        //01双反\\是防止文件名中有歧义字符,用来转义
        File f01 = new File("C:\\Users\\Wind\\Pictures\\Saved Pictures\\风绘.jpg");
        //02正斜杠不用考虑
        File f02 = new File("C:/Users/Wind/Pictures/Saved Pictures/风绘.jpg");
        //03用系统提供的分隔符,好处是可以自适应各种系统
        File f03 = new File("C:"+File.separator+"Users"+File.separator+"风绘.jpg");

        /**
         * 文件字节大小
         * 可以定位到文件夹,但不能这么取大小
         */
        long length = f01.length();

        /**
         * 相对路径:
         *      一般定位到模块中文件,相对到工程下
         *
         */
        File f04 = new File("day08_file_io_app/src/data.txt");
        System.out.println(f04.length());

        /**
         * 定位文件夹,判断存在
         */
        File f05 = new File("C:\\Users");
        boolean exists = f05.exists();
    }
}

2.File类常用API

2.1 文件信息

/**
 * File类常用API
 *  对文件信息的获取
 */
public class FileDemo02 {
    public static void main(String[] args) {
        File f = new File("day08_file_io_app/src/data.txt");
        //1.获取文件绝对路径
        //F:\RerollWorkspace\StudyingBooks\Java\code\javaSEPromax\day08_file_io_app\src\data.txt
        String absolutePath = f.getAbsolutePath();
        //2.获取文件对象创建使用的路径(看情况:相对、绝对)
        String path = f.getPath();//day08_file_io_app\src\data.txt
        //3.获取文件名称,带后缀
        String name = f.getName();//data.txt
        //4.文件大小,字节个数
        long length = f.length();//3
        //5.获取文件最后修改时间(long),需要自己设置输出格式
        long time = f.lastModified();
        //最后修改时间2022/08/06 12:48:33
        System.out.println("最后修改时间"+ new SimpleDateFormat("yyyy/MM/dd HH:mm:ss").format(time));
        //6.判断是文件还是文件夹
        boolean file = f.isFile();//true
        boolean directory = f.isDirectory();//false
    }
}

2.2 创建删除文件(夹)

/**
 * File API
 *  创建 删除
 */
public class FileDemo03 {
    public static void main(String[] args) throws IOException {
        File f = new File("day08_file_io_app/src/data.txt");
        //1.创建新的文件,如果已存在会失败
        //写信息会自动创建文件,一般不需要
        f.createNewFile();

        //2.mkdir 创建一级目录
        File file = new File("C:\\Users\\Wind\\Pictures\\Camera Roll");
        file.mkdir();

        //3.mkdirs创建多级目录
        File file01 = new File("C:\\Users\\Wind\\Pictures\\Camera Roll\\a\\b\\cc");
        file01.mkdirs();

        /**
         * 4.delete 删除文件或者空文件夹,不送入回收站
         * 文件占用一样会被删除
         * 不支持删除非空文件夹
         */
        File dFile = new File("C:\\Users\\Wind\\Pictures\\Camera Roll\\a\\b\\cc");
        dFile.delete();
    }
}

2.3 File类遍历

  • listFiles方法注意事项:
    • 只能遍历当前文件夹下一级文件对象
    • 调用者不存在,返回null
    • 调用者是文件夹,返回null
    • 调用者是空文件夹,返回长度为0的数组
    • 调用者是一个有内容的文件夹,将里面所有文件夹和文件的路径放在File数组返回;
    • 调用者是一个有隐藏文件的文件夹,将里面所有文件夹和文件的路径放在File数组返回,包括隐藏内容;
    • 调用者是一个需要权限才能进入的文件夹时,返回null
/**
 * File的遍历
 */
public class FileDemo04 {
    public static void main(String[] args) {
        File f = new File("C:\\Users\\Wind\\Pictures\\Saved Pictures");
        //1.将当前文件下的所有文件名打入String[]
        String[] listName = f.list();
        for (String name:listName){
            System.out.print(name);
        }

        //2.将当前文件下所有对象存入对象数组
        File[] files = f.listFiles();
        for (File file:files){
            System.out.println(file.getAbsoluteFile());
            //可以循环删除所有文件
        }
    }
}

二、方法递归

1.概述

  • 方法直接调用自己或是间接调用自己称为递归;
  • 递归作为一种算法;
  • 形式:
    • 直接递归:自己调自己
    • 间接递归:自己调其他方法,其他方法回调自己
  • 注意:
    • 递归不控制,会使栈内存溢出,挂掉

2.递归算法三要素

  • 递归公式:f(n)=f(n-1)*n;
    • 复杂问题找规律简单化,层层套
    • 每一次调用递归方法,栈空间都开辟新的方法空间;
  • 递归终结点:f(1);
  • 递归方向必须走向终结点;

3.非规律化递归

3.1案例:搜索文件

/**
 * 非规律化递归
 * 案例:搜索文件
 *  在文件夹下找到要找的文件,返回文件地址
 */
public class RecursionDemo02 {
    public static void main(String[] args) {
        searchFile(new File("F:\\RerollWorkspace\\StudyingBooks\\Java\\java基础\\Java基础从头再来"),"day001");
    }

    public static void searchFile(File dir, String fileName) {
        //保证文件地址有效,且必须是文件夹
        if (dir != null && dir.isDirectory()) {
            File[] files = dir.listFiles();
            //确定是有效文件夹,里面有内容
            if (files != null && files.length > 0) {
                for (File file : files) {
                    if (file.isFile()) {
                        if (file.getName().contains(fileName)) {
                            System.out.println("找到了文件:" + file.getName() + "  地址:" + file.getAbsolutePath());
                            try {
                                //启动软件;不能打开文档、照片
                                //CreateProcess error=193, %1 不是有效的 Win32 应用程序。
                                Runtime runtime = Runtime.getRuntime();
                                runtime.exec(file.getAbsolutePath());
                            } catch (IOException e) {
                                e.printStackTrace();
                            }
                        }
                    } else {
                        searchFile(file, fileName);
                    }
                }
            }
        } else {
            System.out.println("当前地址不是一个有效的文件夹,请检查!");
        }
    }
}

3.2 案例:买啤酒

/**
 * 非规律化递归
 * 案例:买啤酒
 * 现有10元 ; 啤酒2元,4个盖子换一瓶;2个瓶子换一瓶
 * 最后 喝了几瓶酒,剩几个瓶子,几个盖子
 * 答:喝了酒15瓶,剩余瓶子1个,剩余盖子3个
 */
public class RecursionDemo03 {
    //定义静态变量,喝酒瓶数;剩瓶子数;盖子数
    public static int totalNumber;
    public static int lastBottleNumber;
    public static int lastCoverNumber;

    public static void main(String[] args) {
        buy(10);
    }

    public static void buy(int money) {
        //购买酒数
        int buyNumber = money / 2;
        totalNumber += buyNumber;
        lastBottleNumber += buyNumber;
        lastCoverNumber += buyNumber;

        int tempMoney = 0;
        if (lastBottleNumber >= 2) {
            tempMoney += (lastBottleNumber / 2) * 2;
            //换钱后,瓶子数
            lastBottleNumber = lastBottleNumber % 2;
        }
        if (lastCoverNumber >= 4) {
            tempMoney += (lastCoverNumber / 4) * 2;
            //换钱后,瓶子数
            lastCoverNumber = lastCoverNumber % 4;
        }
        if (tempMoney >= 2) {
            buy(tempMoney);
        } else {
            //答:喝了酒15瓶,剩余瓶子1个,剩余盖子3个
            System.out.println("喝了酒" + totalNumber + "瓶,剩余瓶子" + lastBottleNumber + "个,剩余盖子" + lastCoverNumber + "个");
        }

    }
}

三、字符集

1.字符集基础知识

  • 计算机底层可以表示十进制编号;
  • 计算机给人类字符编号存储,编号规则便是字符集;

1.1.ASCII字符集

  • 美国信息交换标准代码;包括数字、英文、符号
  • ASCII使用一个字节存储一个字符,一个字节8位,总共可以表示128个字符,对于英文,数字够用了;

1.2GBK

  • window系统默认码表,兼容ASCII,包含几万个汉字,支持繁体汉字和部分日韩文字;
  • GBK是中国码表,一个中文以两个字节的形式存储,2的16次方65536;
  • 中文在字符集中以负数开头,方便读取

1.3 Unicode码表

  • unicode(统一码、万国码、单一码)计算机领域的一项业界字符编码标准;
  • 容纳世界上大多数国家的所有常见文字和符号;
  • Unicode会先通过UTF-8,UTF-16,UTF-32的编码成二进制后存储入计算机
    • 最常用的是UTF-8,一个中文一般以三个字节码的形式存储
    • UTF-8兼容ASCII,英文和数字在任何国家字符集都占1个字节
    • 技术人员应该使用UTF-8
    • 编码前后的字符集需要一致,否则会中文乱码;但是英文和数字不会乱码

2.字符集编码解码操作

/**
 * 字符集编码和解码
 */
public class CharsetDemo01 {
    public static void main(String[] args) throws IOException {
        //1.编码
        String name = "123abc我爱你中国";
        //默认 UTF-8
        byte[] bytesUTF = name.getBytes();
        int lengthUTF = bytesUTF.length;//21 3+3+5*3
        System.out.println(lengthUTF);
        //[49, 50, 51, 97, 98, 99, -26, -120, -111, -25, -120, -79, -28, -67, -96, -28, -72, -83, -27, -101, -67]
        System.out.println(Arrays.toString(bytesUTF));
        //自定义GBK
        byte[] bytesGBK = name.getBytes("GBK");
        int lengthGBK = bytesGBK.length;//16 3+3+5*2
        System.out.println(lengthGBK);
        //[49, 50, 51, 97, 98, 99, -50, -46, -80, -82, -60, -29, -42, -48, -71, -6]
        System.out.println(Arrays.toString(bytesGBK));

        //2.解码
        String rsUTF = new String(bytesUTF);
        //123abc我爱你中国
        System.out.println(rsUTF);
        String rsGBK = new String(bytesUTF,"GBK");
        //123abc鎴戠埍浣犱腑鍥�
        System.out.println(rsGBK);
    }
}

RecordDate:2021/08/15