Java基础:file、方法递归、IO流

File类概述

File类在包 java.io.File下,代表操作系统的文件对象(文件、文件夹)
File类提供了诸如:定位文件获取文件本身信息,删除文件,创建文件(文件夹)等功能

File类创建对象

//构造方法
File (String pathname ) 
File (File parent, String child)
File(File parent String , String child)

创建File对象(指定文件的路径)

路径写法:

  1. D:\study\xuesheng.jpeg
  2. D:/study/xuesheng.jpeg

创建File对象(支持绝对路经,支持相对路径(重点))

绝对路经:从盘符开始,依赖当前系统
相对路经:一般定位于模块中的文件的,定位到工程下

File f = new File(“file-io-app.src.data.txt”);

File 创建对象(可以是文件也可以是文件夹)

file常用API

判断文件类型,获取文件信息

File f = new File (D:\\study\\xuesheng.jpeg”);
long time = f.lastModified();
System.out.println(“最后的修改时间是”+new SimpleDateFormat(“yyyy/MM/did HH:mm:ss”).format(time));

创建文件,删除文件功能



删除文件,占用也可以删除

遍历文件夹

//1. 定位一个目录
File f = new File ("D:/study");
String [] names = f.list();
for(String name:names){
    System.out.println("name");
}
//2.只能遍历 一级文件对象
File files = f.listFiles();
for(File file:files){
    System.out.println("file.getAbsolutePath()");
}
//3.listFiles 注意事项:
//当调用者不存在时,返回null
//当调用者是一个文件时,返回null
//当调用着是一个空文件夹时,返回一个长度为0的数组
//当调用者是一个有内容的文件夹时,将文件和文件夹的路径放在File数组中
//当调用者是一个有隐藏文件的文件夹时,将里面所有的文件和文件夹的路径放在File数组中返回,包含隐藏内容

方法递归(文件搜索)

递归的形式和特点

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

直接递归:方法自己调用自己
间接递归:方法调用其他方法,其他方法又回调方法自己

递归的算法流程,核心要素

导学-计算1-n的阶乘
公式为f(n) = f(n-1)*n;

非规律化递归案例-文件搜索

需求:文件搜索,从C盘中,搜索出某个文件名称并输出绝对路径
分析:

  1. 先定位出的应该是一级文件对象
  2. 遍历所有一级文件对象,判断是否为文件
  3. 如果是文件,判断是否为自己想要
  4. 如果是文件夹,需要继续递归进去重复上述过程

import java.io.File;

public class RecursionDemo {
    public static void main(String[] args) {
        //2. 传入目录 和 文件名称
        File file = new File("D:/");
        searchFile(file,"dhdgffkkebhmkfjojejmpbldmpobfkfo");
    }

    /**
     *1. 搜索某个目录下的全部文件,找到我们想要的
     * @param dir  被搜索的源目录
     * @param fileName   被搜索的文件名称
     */
    public static void searchFile(File dir,String fileName){
        //3. 判断dir是否为目录
        if(dir!=null && dir.isDirectory()){
            //可以找了
            //4. 提取当前目录下的以及文件对象
            File files[] = dir.listFiles();
            //5. 判断是否存在一级文件对象,存在在遍历
            if(files !=null&&files.length!=0){
                for (File file :files){
                    //6. 判断当前的一级文件对象是文件还是目录
                    if(file.isFile()){
                        //7. 是不是我们要找的
                        if(file.getName().contains((fileName))){
                            System.out.println("找到了"+file.getAbsoluteFile());
                        }
                        //8. 是文件夹

                    }else {
                        searchFile(file,fileName);
                    }
                }

            }
        }else{
            System.out.println("对不起当前搜索的位置不是文件夹");
        }
    }
}

字符集

常见字符集介绍

基础知识

  1. 计算机底层不能直接存储字符的,计算机中底层只能存储二进制(0,1)
  2. 二进制是可以转换为十进制的
  3. 计算机底层是可以表示十进制编号。计算机可以给文类字符进行编号存储,这套编号规则就是字符集
    ASCII字符集
    GBK
    Unicode码表(统一码,万国码):由于Unicode会先通过UTF-8的编码称二进制后再存储到计算机


字符串常见的字符组成:
英文和数字等在任何国家的字符集中都占一个字节
GBK字符中一个英文字符占2个字节
UTF-8编码中一个中文一般占三个字节
编码前的字符集和编码好的字符集必须一致,否则会出现中文符乱码

字符集的编码,解码操作



import java.io.UnsupportedEncodingException;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;

public class Test {
    public static void main(String[] args) {
        //1. 编码:把文字转换为字节(使用指定编码)
        String name = "abc我爱你中国";
        byte[] bytes = new byte[0];//以当前代码默认字符集进行编码(UTF-8)
       // bytes = name.getBytes();
        try {

            bytes = name.getBytes("GBK");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        System.out.println(bytes.length);
        System.out.println(Arrays.toString(bytes));

        //2. 解码:把字节转换成对应的中文形式(编码前和编码后的字符集必须一致,否则乱码)
        String rs = null;//默认UTF-8
        try {
            rs = new String(bytes,"GBK");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        System.out.println(rs);
    }
}

IO流概述

分类

按流的方向分
IO流也称为输入,输出流,就是用来读写数据的
I表示input,是从数据从硬盘文件读入到内存的过程,称之输入,负责读
O表示output,是内存程序的数据从内存写出到硬盘文件的过程,称之为输出,负责写
按流中的数据最小单位分
字节流
字符流
组合

概念抽象类
字节输入流以内存为基准,来自磁盘文件/网络中的数据以字节的形式读入到内存中去的流InputStream
字节输出流以内存为基准,把来自内存中的数据以字节写出到磁盘文件/网络中去的流OutputStream
字符输入流以内存为基准,来自磁盘文件/网络中的数据以字符的形式读入到内存中去的流Reader
字符输出流以内存为基准,把来自内存中的数据以字符写出到磁盘文件/网络中去的流Writer

字节流的使用

字节流适合做一切文件数据的拷贝,任何文件底层都是字节,拷贝是一字不漏地转移字节,只要前后的文件格式,编码一致没有任何问题。

字节输入流:每次读取一个字节





输出结果
在这里插入图片描述


import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;

public class FileInputSream {
    public static void main(String[] args) {

        try {
            //1. 创建一个文件字节输出流管道与源文件接通
            //InputStream is = new FileInputStream(new File("SuanFa\\logback-APP\\srd\\data"));
            //简写
            InputStream is = new FileInputStream("logback-APP\\src\\data");
//            //读取一个字符并返回
//            int bi = is.read();
//            System.out.println((char) bi);
            int b ;
            while ((b = is.read())!=-1){
                System.out.print((char) b);
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

每次读取一个字节存在的问题
性能比较慢
读取中文字符输出无法避免乱码问题

字节输入流:每次读取一个字节数组


在这里插入图片描述

在这里插入图片描述


import java.io.FileInputStream;
import java.io.InputStream;

public class FileInputSream_Demo02 {
    /**
     *目标:使用文件字节输入流每次读取一个字节数组的数据
     */
    public static void main(String[] args) throws Exception{
        //1. 创建一个文件字节输入流管道与源文件接通
        InputStream is = new FileInputStream("logback-APP\\src\\data");

//        //2. 定义一个字节数组,用于读取字节数组
//        byte[]  buffer = new byte[3];
//        int len1 = is.read(buffer);
//        System.out.println("读取了几个字节"+len1);
//        String rs1 = new String(buffer);
//        System.out.println(rs1);
//
//        int len2 = is.read(buffer);
//        System.out.println("读取了几个字节"+len2);
//        String rs2 = new String(buffer);
//        System.out.println(rs2);
//
//        int len3 = is.read(buffer);
//        System.out.println("读取了几个字节"+len3);
//        //读取多少,倒出多少
//        String rs3 = new String(buffer,0,len3);
//        System.out.println(rs3);
//
        //使用循环
        byte[] buffer = new byte[3];
        int len ;
        while((len=is.read(buffer))!=-1){
            //读取多少,倒出多少
            System.out.print(new String(buffer,0,len));
        }

    }
}

每次读取一个字节数组存在的问题
性能得到了提升
读取中文字符输出无法避免乱码问题

字节输入流:一次读完全部字节

如何使用字节输入流读取中文内容输出不出现乱码
定义一个与文件一样大的字节数组,一次性读取完文件的全部字节
直接把文件数据读取到一个字节数组可以避免乱码存在的问题、
如果文件过大,字节数组可能引起内存溢出

方式一:自己·定义一个与文件大小一样大,然后使用读取字节数组的方法,一次性读取完成

import java.io.File;

import java.io.FileInputStream;
import java.io.InputStream;

public class FileInputSream_Demo03 {
    /**
     *目标:使用文件字节输入流一次读取文件中的所有数据,可以解决中文乱码问题
     */
    public static void main(String[] args) throws Exception{
        //1. 创建一个文件字节输入流管道与源文件接通
        File f = new File("logback-APP\\src\\data");
        InputStream is = new FileInputStream(f);

        //2.定义一个字节数组与文件的大小一样大
        byte [] buffer = new byte[(int)f.length()];
        int len = is.read(buffer);
        System.out.println("读取了多少字节"+len);
        System.out.println("文件大小"+f.length());
        System.out.println(new String(buffer));

    }
}

方法二:官方为字节输入流InputStream提供了如下API可以将字节把文件全部数据提取到一个字节数组中

bytes []  buffer = is.readAllBytes();

字节输出流:写字节数据到文件

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

import java.io.FileOutputStream;
import java.io.OutputStream;
import java.nio.charset.StandardCharsets;

public class FileOutputSream_Demo01 {
    public static void main(String[] args) throws Exception{
        //1. 创建一个文件字节输出流管道与目标文件接通
        OutputStream os = new FileOutputStream("logback-APP\\\\src\\\\data",true);
       // OutputStream os = new FileOutputStream("logback-APP\\\\src\\\\data");//先清空之前的数据,写新的数据
        //2. 写数据出去
        //a. public void write(int a):写一个字节出去
        os.write('a');
        os.write(98);
       // os.write('徐');
        os.write("\r\n".getBytes(StandardCharsets.UTF_8));//如果只有\n在windows系统中会是换行符,但是在linux系统中将不能识别,\r\n在很多系统中均适用

        //b. public void write(byte[] buffer):写一个字节数组出去
        byte [] buffer = {'a',97,98,99};
        os.write(buffer);
        os.write("\r\n".getBytes(StandardCharsets.UTF_8));
        byte [] buffer2 = "我是中国人".getBytes(StandardCharsets.UTF_8);
        os.write(buffer2);
        os.write("\r\n".getBytes(StandardCharsets.UTF_8));
        //c. public void write(byte[] buffer):写一个字节数组的一部分出去
        byte [] buffer3 = {'a',97,98,99};
        os.write(buffer3,0,3);
        os.write("\r\n".getBytes(StandardCharsets.UTF_8));


        os.flush();  //写数据一定要刷新数据
        os.close();//释放资源,包含了刷新的!关闭后流不可以再用
    }
}

资源释放的方式

try-catch-finally

finally:在处理异常时提供finally块来执行所有清除操作
特点:被finally控制的语句最终一定会执行,除非JVM退出(System.exit();)
作用:finally代码块是最终一定要执行的,可以在代码执行完毕的最后用于释放资源

//格式
try{

}catch(Exception e){

}finally{

}

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.charset.StandardCharsets;

public class FileOutputSream_Demo01 {
    public static void main(String[] args) {
        OutputStream os = null;
        try {
            //1. 创建一个文件字节输出流管道与目标文件接通
            os = new FileOutputStream("logback-APP\\\\src\\\\data",true);
            // OutputStream os = new FileOutputStream("logback-APP\\\\src\\\\data");//先清空之前的数据,写新的数据
            //2. 写数据出去
            //a. public void write(int a):写一个字节出去
            os.write('a');
            os.write(98);
            // os.write('徐');
            os.write("\r\n".getBytes(StandardCharsets.UTF_8));//如果只有\n在windows系统中会是换行符,但是在linux系统中将不能识别,\r\n在很多系统中均适用

            os.flush();  //写数据一定要刷新数据
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            
                try {
                    if(os!=null)os.close();//释放资源,包含了刷新的!关闭后流不可以再用
                } catch (IOException e) {
                    e.printStackTrace();
                }   
        }
    }
}

try-with-resource

try(定义流对象){
        可能出现异常的代码
}catch(异常类名 变量名){
        异常处理代码
}

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.charset.StandardCharsets;

public class FileOutputSream_Demo01 {
    public static void main(String[] args) {

        try (
                //这儿里面只能放置资源对象,用完会自动关闭
                //自动调用资源对象的close方法关闭资源(即使出现异常也会做关闭操作)
                //1. 创建一个文件字节输出流管道与目标文件接通
               OutputStream os = new FileOutputStream("logback-APP\\\\src\\\\data",true);
        // OutputStream os = new FileOutputStream("logback-APP\\\\src\\\\data");//先清空之前的数据,写新的数据
                ){

            //2. 写数据出去
            //a. public void write(int a):写一个字节出去
            os.write('a');
            os.write(98);
            // os.write('徐');
            os.write("\r\n".getBytes(StandardCharsets.UTF_8));//如果只有\n在windows系统中会是换行符,但是在linux系统中将不能识别,\r\n在很多系统中均适用

            os.flush();  //写数据一定要刷新数据
        } catch (IOException e) {
            e.printStackTrace();
        }


    }
}

JDK7和JDK9中的()中只能 放置资源对象,否则报错;这里的资源就是实现了Closeable/AutoCloseable接口的类对象

字符流的使用

字节流读取中文输出会存在问题:会乱码或内存溢出

文件字符输入流:一次读取一份字符


import java.io.FileReader;

import java.io.Reader;

public class FileReaderDemo01 {
    //目标:每次读取一个字符
    public static void main(String[] args) throws Exception {
        //1. 创建一个字符输入流管道于与源文件接通
        Reader fr = new FileReader("logback-APP\\src\\data");
        //2. 读取一个字符
//        int code = fr.read();
//        System.out.println(code);
//
        //3. 使用循环读取字符
        int code ;
        while ((code=fr.read())!=-1){
            System.out.print((char)code);
        }
    }
}

在这里插入图片描述
在这里插入图片描述
字节流的好处:读取中文字符不会出现乱码(如果代码和文件编码一致)
每次读取一个字符会存在的问题:性能较慢

文件字符输入流:一次读取一个字符数组

import java.io.FileReader;
import java.io.Reader;

public class FileReaderDemo02 {
    //目标:每次读取一个字符
    public static void main(String[] args) throws Exception {
        //1. 创建一个字符输入流管道于与源文件接通
        Reader fr = new FileReader("logback-APP\\src\\data");

       //2. 用循环每次读取一个字符数组
        char [ ] buffer = new char[1024];
        int len;
        while ((len = fr.read(buffer))!=-1){
            String rs = new String(buffer,0,len);
            System.out.print(rs);
        }

    }
}

每次读取一个字符数组的优势:性能较好

文件字符输出流

import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;

public class FileWriterDemo {
    public static void main(String[] args) throws Exception {
        //1. 创建一个字符输出流管道与原文件接通
       // Writer fw = new FileWriter("logback-APP\\src\\data");//每次写进去,都会先清空
        Writer fw = new FileWriter("logback-APP\\src\\data",true);
        //a. public void write(int c):写一个字符出去
       fw.write(98);
       fw.write('s');
       fw.write('徐');
       fw.write("\r\n");
        fw.write("abc 我是个中国人");
        fw.write("\r\n");

        //c. public void write(char[] buffer):写一个字符数组出去
        fw.write("abc我是中国人".toCharArray());
        fw.write("\r\n");
        //d. public void write(String c,int len):写一个字符串的一部分出去
        fw.write("abc我是中国人",0,4);
        fw.write("\r\n");
        //e. public void write(char[] buffer,int len):写一个1字符数组的一部分出去
        fw.write("abc我是中国人".toCharArray(),0,4);
        fw.write("\r\n");
        fw.flush();
        fw.close();

    }
}

在这里插入图片描述

字节流,字符流总结

字节流,字符流如何选择使用:

  1. 字节流适合做一切文本数据的拷贝
  2. 字节流不适合读取中文输出
  3. 字符流适合作、做文本文件的操作(读,写·)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

wilihelmi

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值