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

2023-10-07  本文已影响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

缺点:

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);

字符缓冲流

新增了按行读取的功能

 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把键值对信息存入到属性文件中
        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文件夹中并且加到依赖库

上一篇 下一篇

猜你喜欢

热点阅读