美文网首页
JavaSE进阶 file,方法递归,io流

JavaSE进阶 file,方法递归,io流

作者: 扶光_ | 来源:发表于2023-10-07 08:24 被阅读0次

    File类

    在java.io.File下,提供了文件本身的信息,删除文件,创建文件等

       //创建file对象,指定文件路径
            File f = new File("C:\\Users\\lucas的电脑\\Desktop\\封面图\\1.gif");
            long size = f.length();//文件字节大小
            System.out.println(size);
    
            //2 file创建对象支持相对路径 和 绝对路径  是在工程下
    
            //file对象代表文件夹 exists()判断这个路径是否存在
    

    file一些常用api

     File f = new File("C:\\Users\\lucas的电脑\\Desktop\\封面图\\1.gif");
            //获取绝对路径
            System.out.println(f.getAbsolutePath());
            //获取定义的路径
            System.out.println(f.getPath());
            //获取文件名称
            System.out.println(f.getName());
            //获取文件字节大小
            System.out.println(f.length());
            //获取文件最后修改时间 毫秒值
            long time = f.lastModified();
            System.out.println(new SimpleDateFormat("yyyy/MM/dd HH:mm:ss").format(time));
            //判断是否是文件
            System.out.println(f.isFile());//true
    

    创建和删除文件或文件夹

    File f = new File("bug\\src\\com\\hx\\file\\data.txt");
            //创建文件
            System.out.println(f.createNewFile());//几乎不用
            //创建一级目录
            File f2 = new File("bug\\src\\com\\hx\\text");
            f2.mkdir();
            //创建多级目录
            File f3= new File("bug\\src\\com\\hx\\text\\aaa\\bbb\\ccc\\ddd");
            f3.mkdirs();
            //删除文件或空文件夹
            f2.delete();
    

    遍历文件

    //定位一个目录
            File f = new File("C:\\Users\\lucas的电脑\\Desktop\\封面图");
            //获取当前目录下一级文件名称放在字符串数组中返回
           String[] names = f.list();
            for (String name : names) {
                System.out.println(name);
            }
            //遍历一级文件对象  在对象数组中去返回
            File[] f1 = f.listFiles();
            for (File file : f1) {
                System.out.println(file.getName());
            }
    
    

    listFiles只能拿到一级目录下的所有内容,再想拿到一级目录中的目录中文件拿不到,所有出现方法递归。

    二,方法递归

    方法直接调用自己或间接调用自己的形式称为方法递归

    直接递归

     public static void main(String[] args) {
        text();
        }
        public static void text(){
            System.out.println("========text执行======");
            text();//自己直接调用自己  直接递归
        }
    

    没有控制终止,会出现死循环,导致栈内存溢出

    间接递归

    间接调用自己出现死循环

    public static void main(String[] args) {
        text1();
        }
        public static void text(){
            System.out.println("========text执行======");
            text1();//自己直接调用自己  直接递归
        }
        public static void text1(){
            System.out.println("========text执行======");
            text();//自己直接调用自己  直接递归
        }
    

    如算5的阶乘 54321

        public static void main(String[] args) {
          int result =   fn(5);
            System.out.println(result);
        }
        public static int fn(int num){
            if(num==1){
                return 1;
            }else {
              return num* fn(num-1);
            }
        }
    
    执行流程

    递归算法理论

    • 递归公式
    • 递归终结点
    • 递归方向必须走向终结点

    非规律化递归

    需求:从c盘中搜索某个文件名称并输出他的绝对路径
    先定位,再遍历,如果是文件判断是不是想要的,是文件夹继续递归

    public static void main(String[] args) {
    
            searchFile(new File("D:/"),"制定学习.txt");
        }
        public static void searchFile(File dir,String name){
            if(dir!=null&&dir.isDirectory()){
                //可以寻找
                File[] files = dir.listFiles();//null
                //判断是否存在一级文件对象
                if(files!=null&&files.length>0){
                    //开始遍历
                    for (File file : files) {
                        if(file.isFile()){
                            //说明是文件 判断是否需要
                            if (file.getName().equals(name)){
                                System.out.println(file.getAbsolutePath());
                            }
                        }else{
                            //继续遍历 也就开将上面的步骤开始递归
                            searchFile(file,name);
    
                        }
                    }
                }
            }else{
    //            当前搜索的不是文件夹
                System.out.println("您搜索的不是文件夹");
            }
        }
    

    三,字符集

    计算机底层不可以直接存储字符的,计算机底层只能存储二进制(0 1)
    二进制可以转换十进制
    所以计算机底层可以表示十进制编号,计算机可以给人类字符进行编号存储,如a=97 二进制(01100001)

    ASCII字符集(美国信息交换标准代码)

    包括了数字,英文,符号
    使用一个字节存储一个字符,一个字节是8位

    GBK编码格式

    windows系统默认码表,兼容ASCII码表,包含了几万个汉字
    gbk是中国的码表,一个中文以2个字节存储

    Unicode码表

    万国码,因为全世界每个国家都自己有一套编码不利于流通,所以搞了一套通用编码
    最为常见的就是UTF-8,三个字节表示一个中文

    编码转换

    字符集编码和解码的操作

       //编码
            String name = "abc呜呜呜";
            byte[] arr = name.getBytes("utf-8"); //以当前代码默认字符集进行编码(utf-8)
            System.out.println(Arrays.toString(arr));
            System.out.println(arr.length);
            //解码
            String s = new String(arr,"utf-8");
            System.out.println(s);
    
    结果
    因为utf-8汉字代表三个字节 所以3*3=9 外加3个英文
    我们发现中文汉字都是负数,所以在utf-8编码中负数是汉字
    编码和解码必须一致,否则乱码

    四,IO流(输入输出流)

    读写数据的


    io流流程
    io流分为

    字节流适合读取一切内容(适合读文本)
    字符流适合读取文本内容

    字节输入流

    1 每次只读一个字节

    从硬盘读取到内存中

         //输入流 从硬盘读到内存
            InputStream is = new FileInputStream("D:\\code\\javasepro\\bug\\src\\data.txt");
            //读取一个字节返回
            int num = is.read();//没有可读的返回-1 
            System.out.println((char)num);//转换为char   a
    

    缺点:

    • 1.性能慢
    • 2.读中文乱码 (因为中文2个字节)

    2 每次读取一个字节数组

    //输入流 从硬盘读到内存
            InputStream is = new FileInputStream("D:\\code\\javasepro\\bug\\src\\data.txt");
            //定义一个数组,用于读取字节
            byte[] buffer = new byte[3];
            int b = is.read(buffer);//每次读取字节数
            String s = new String(buffer,0,b);
            System.out.println(s);
    
    • 依然无法解决中文输出乱码问题

    3 一次读取完文件全部字节

    读取中文不乱码,需要定义一个与文件一样大的字节数组,一次性读取完文件全部字节
    但这样有一个缺点,如果文件过大字节数组可能引起内存溢出.

        //输入流 从硬盘读到内存
            File file = new File("D:\\code\\javasepro\\bug\\src\\data.txt");
            InputStream is = new FileInputStream(file);
            //定义一个与字节数组与文件一样大
            byte []buffer = new byte[(int) file.length()];
    
           int len =  is.read(buffer);
            System.out.println(len);
            System.out.println(file.length());
            System.out.println(new String(buffer));
    

    有一个api可以直接读取全部内容
    readAllBytes

    字节输出流

      //创建一个输出流与目标文件相连
      //会清空之前的数据 再写新数据
            OutputStream os = new FileOutputStream("D:\\code\\javasepro\\bug\\src\\out.txt");
            //向文件中写数据
            os.write('a');
            os.write(98);
            //写中文 还得用桶装
            byte[] buffer = "中文汉字".getBytes(StandardCharsets.UTF_8);//字符串转换为字节数组
            os.write(buffer);
            os.flush();//写数据必须刷新数据 不关闭流
            os.close();//释放资源,包含刷新
    

    追加数据

         OutputStream os = new FileOutputStream("D:\\code\\javasepro\\bug\\src\\out.txt",true);
    

    文件拷贝

     try {
    
    //        可以拷贝一切文件
               InputStream fileInputStream = new FileInputStream("D:\\code\\javasepro\\bug\\src\\out.txt");
               //创建输出流
               FileOutputStream fileOutputStream = new FileOutputStream("D:\\newcopy.txt");
    
               //定义字节数组转移数据
               byte[] buffer = new byte[1024];
               int len ;//记录每次读取字节数
               while ((len=fileInputStream.read(buffer))!=-1){
                   fileOutputStream.write(buffer,0,len);
               }
               System.out.println("复制完成");
               fileOutputStream.close();
               fileInputStream.close();
           }catch (Exception e){
               e.printStackTrace();
           }
    

    最好使用 try-catch-finally提供的finally来进行释放内存,无论成功与否都需要释放内存
    还有一种try-with-resource来进行释放
    try(里面放资源){

    }
    catch(Exception e){
    //
    }
    这样会自动调用释放资源

    字符流

    字符输入流

    每次读取一个字符

    不会出现中文乱码
    将磁盘上的数据以字符形式读取到内存中

     //先创建管道
            Reader fileReader = new FileReader("D:\\code\\javasepro\\bug\\src\\data.txt");
            //读取字符返回
            int code = fileReader.read();
            System.out.println((char)code);
    

    性能很慢

    一次读取一个字符数组

       //先创建管道
            Reader fileReader = new FileReader("D:\\code\\javasepro\\bug\\src\\data.txt");
            char[] arr = new char[1024];
            int data;
            while((data=fileReader.read(arr))!=-1){
                String rs = new String(arr,0,data);
                System.out.println(rs);
            }
    

    字符输出流

    
            Writer fileWriter = new FileWriter("D:\\code\\javasepro\\bug\\src\\data2.txt");//每次启动会清空
            //写一个字符出去
            fileWriter.write('是');
            fileWriter.flush();
            //写一个字符串
            fileWriter.write("一个字符串");
            //写一个字符数组
            char[] arr = "南大街看".toCharArray();
            fileWriter.write(arr);
            //写字符串一部分
            fileWriter.write("一个字符串",0,3 );
    
    

    五,缓存流

    自带缓冲区,可以提高原始字节流,字符流读写数据性能
    之所以快,是因为开辟了一块内存空间,读写先在内存中

    原理:将原始流进行包装成缓冲输入流,用缓冲输入流的管道(自带8kb缓冲池)

    字节缓冲流

    • 字节缓冲输入流
     InputStream fileInputStream = new FileInputStream("D:\\code\\javasepro\\bug\\src\\out.txt");
            //        将原始流包装成字节输入缓冲流
            InputStream bis =  new BufferedInputStream(fileInputStream);
            //创建输出流
            OutputStream fileOutputStream = new FileOutputStream("D:\\newcopy.txt");
            //        将原始流包装成字节输出缓冲流
            OutputStream bos = new BufferedOutputStream(fileOutputStream);
    
    • 字节缓冲输出流
      OutputStream bos = new BufferedOutputStream(fileOutputStream);

    字符缓冲流

    新增了按行读取的功能

    • 字符缓冲输入流
     try(
                   Reader f =  new FileReader("D:\\code\\javasepro\\bug\\src\\data.txt");
                  BufferedReader br =  new BufferedReader(f);
            ) {
                String rs ;
                while ((rs = br.readLine())!=null){
                    System.out.println(br);
                }
    
            }catch (Exception e){
                e.printStackTrace();
            }
    
    • 字符缓冲输出流
    
            Writer fw = new FileWriter("D:\\code\\javasepro\\bug\\src\\data2.txt");//每次启动会清空
            BufferedWriter bw = new BufferedWriter(fw);
    bw.newLine();//换行
    

    六,转换流

    之前我们使用字符流没有乱码是因为,输入和输出(读写)都是utf-8的编码,代码编码和文件编码
    如你的代码是utf-8,但你要读别人gbk的文件。

    字符输入转换流

    提前文件的原始字节流,原始字节不会出现问题,然后把字节流以指定编码转换为字符输入流,这样就不会乱码
    InputStream is = new FileInputStream("d:/dada.txt");
    Reader rd = new inputStreamReader(is,"gbk");//以gbk编码转换为字符输入流

    字符输出转换流

    字符以指定编码获取字节后再使用字节输出流写出去
    Writer wt = new OutputStreamWriter("字节流");

    七,对象序列化

    以内存为基准,把内存中的对象存储到磁盘文件中去,称为对象序列化

    对象文件输出流(ObjectOutputStream)

    把对象数据存储到文件中

      //1 创建学生对象
            Student s = new Student("侯旭",22,"篮球");
            //2 对象序列化 使用对象字节输出流包装字节输出流
            ObjectOutputStream OOS = new ObjectOutputStream(new FileOutputStream("D:\\code\\javasepro\\bug\\src\\2.txt"));
            //3 直接调用序列方法写入
            OOS.writeObject(s);
            //4 释放资源
            OOS.close();
    

    但是在Student类中必须实现Serializable接口,目的是对象要序列化必须实现序列化接口 要告诉java虚拟机以序列化保存文件

    八,对象反序列化

    以内存为基准,把存储到磁盘文件中的对象恢复到内存中的对象,称为对象反序列化

    ObjectInputStream ois = new ObjectInputStream(new FileInputStream("D:\\code\\javasepro\\bug\\src\\2.txt"));
            Student s = (Student) ois.readObject();//提取出来时是object类,需要强转一下
            System.out.println(s);
    

    Student{name='侯旭', age=22, hobby='篮球'}
    但是这样会暴露你的年龄,如果不想暴露就不参与序列化,在成员变量前加transient,这样不参与序列化

    最好在实体类中加序列号版本
    private static final long serialVsersionUid = 1;

    八,打印流

    image.png

    打印流:可以更方便,高效的写数据到文件中,可以实现打印什么数据就是什么数据97就是97,而不是字符a

    PrintStream ps = new PrintStream('写文件路径');//字节输出流
    PrintWriter ps = new PrintStream('写文件路径');//字符输出流  打印数据无区别.只能写字符数据出去
    ps.println(97);
    ps.println(你好);
    ps.println(97.256);
    

    properties属性集对象

    是一个map集合,比hashmap更好用

    • properties核心作用
      1 代表的是一个属性文件,可以把自己对象中的键值对信息存入到一个属性文件中去
      属性文件是以后缀.properties接尾的文件,里面内容是key=value,后续做系统配置信息的

    • properties结合io流存储方法

     //使用properties把键值对信息存入到属性文件中
            Properties properties = new Properties();
            properties.setProperty("admin","123456");
            properties.setProperty("user1","123456");
            properties.setProperty("user2","abc");
            properties.setProperty("user3","123456");
            System.out.println(properties);
            //保存到文件中 参数1 目标地址 参数2 保存心得
            properties.store(new FileWriter("D:\\code\\javasepro\\bug\\src\\user.properties"),"this a bug");
    
    • 读取 文件中键值对信息
     Properties properties = new Properties();
            System.out.println(properties);
            //加载属性文件中的键值对到属性对象properties中
            properties.load(new FileReader("D:\\code\\javasepro\\bug\\src\\user.properties"));
            System.out.println(properties);
            //根据键取数据
            String psw = properties.getProperty("user1");
            System.out.println(psw);// 123456
    

    九,Commons IO 框架

    由第三方提供的一种操控io的类库,可以提高io功能开发的效率,
    核心类库FileUtils和IoUtils

    首先去官网下载,然后将jar包放在lib文件夹中并且加到依赖库

    相关文章

      网友评论

          本文标题:JavaSE进阶 file,方法递归,io流

          本文链接:https://www.haomeiwen.com/subject/ggijbdtx.html