day15【File类、递归、字节流】.相对路径和绝对路径的概念、递归求和、文件搜索、IO流的概述、Java中IO的四大流、字节流练习:复制图片

day15【File类、递归、字节流】

反馈和复习
1.内容太少,有点担心
2.内容讲的太浅(多线程一块)
昨天(JDK8):
1.Lambda
    标准格式:(参数)->{方法体;return 返回值;}
	省略格式:a.参数类型可以省略 
        	b.如果一个参数,小括号可以省略 
        	c.如果{}中只有一句代码,那么{};return可以省略
2.Stream    
    API:
		stream.foreach(s->System.out.println(s));
		stream.count();
		stream.skip(2);
		stream.limit(2);
		stream.filter(s->s.startsWith("xx"));
		stream.map(s->s.charAt(0));
		Stream.concat(s1,s2);
今日内容
今天+(上课的)明天+(上课的)后天: IO流
1.File类(了解)
2.递归(了解)
3.IO概念(说出!)
4.字节流(字节输出流,字节输入流)【重点】     

一.File类

1.File类的作用
File类可以表示文件或者文件夹
2.File类的构造
public File(String path);

public File(String parent,String child);

public File(File parent,String child);

public class FileDemo01 {
    public static void main(String[] args) {
        //1.构造方法1
        File f1 = new File("C:\\Users\\Administrator\\Desktop\\temp\\aaa");
        System.out.println(f1);
        //2.构造方法2
        File f2 = new File("C:\\Users\\Administrator","Desktop\\temp\\aaa");
        System.out.println(f2);

        //2.构造方法3
        File parent = new File("C:\\Users\\Administrator");
        File f3 = new File(parent,"Desktop\\temp\\aaa");
        System.out.println(f3);
    }
}
3.File类的获取方法
public String getAbsolutePath(); 获取该File对象的绝对路径
  
public String getPath(); 获取该File对象构造时,传入的路径    
    
public String getName(); 获取该File对象的代表的文件或者文件夹的名字
    
public long length(); 获取该File对象的大小(单位为字节)    

public class FileDemo02 {
    public static void main(String[] args) {
        //File类的获取方法
        File ff = new File("C:\\Users\\Administrator\\Desktop\\temp\\aaa\\1.txt");
        //1.getAbsolutePath
        String absolutePath = ff.getAbsolutePath();
        System.out.println(absolutePath);

        //2.getPath
        String path = ff.getPath();
        System.out.println(path);

        //3.getName
        String name = ff.getName();
        System.out.println(name);

        //4.length
        long len = ff.length();
        System.out.println(len+"字节");
    }
}

注意:length方法只能获取文件的大小,不能获取文件夹的大小
4.相对路径和绝对路径的概念【重点掌握】
绝对路径: 是指以盘符开头的路径
    比如: "C:\Users\Administrator\Desktop\temp\aaa\1.txt"
相对路径: 以当前项目的根目录为起始的路径   
	比如: "1.txt"  "aa\\1.txt"
public class FileDemo03 {
    public static void main(String[] args) {
        //1.绝对路径
        File ff1 = new File("C:\\Users\\Administrator\\Desktop\\temp\\aaa\\1.txt");
        //2.相对路径
        File ff2 = new File("1.txt"); //表示当前项目根目录下的1.txt
        File ff3 = new File("aa\\1.txt"); //表示当前项目根目录下的aa文件夹里的1.txt
    }
}
5.File类的判断方法
public boolean exists(); 判断该File对象代表文件和文件夹是否存在
public boolean isDirectory(); 判断该File对象说代表是否是文件夹
public boolean isFile(); 判断该File对象说代表是否是文件
    
public class FileDemo04 {
    public static void main(String[] args) {
        //1.创建一个File对象
        File ff = new File("1.txt");//相对路径
        //2.判断是否存在
        boolean b = ff.exists();
        System.out.println("是否存在:" + b);

        //3.判断是文件呢??还是文件夹呢???
        boolean directory = ff.isDirectory();
        System.out.println("是文件夹吗?"+directory);
        boolean file = ff.isFile();
        System.out.println("是文件吗?"+file);
    }
}    
6.File类的创建删除方法
public boolean mkdir();创建单级文件夹,返回值表示是否创建成功   
public boolean mkdirs();创建多级文件夹,返回值表示是否创建成功        
public boolean createNewFile();创建文件,返回值表示是否创建成功  
public boolean delete();删除该File对象代表的文件或者空文件夹,返回值表示是否删除成功      
public class FileDemo05 {
    public static void main(String[] args) throws IOException {
        //1.创建一个File对象
        File ff = new File("2.txt");
        //2.创建文件
        boolean b1 = ff.createNewFile();
        System.out.println("是否创建成功呢??"+b1);
        //3.创建文件夹
        boolean b2 = ff.mkdir();
        System.out.println("是否创建成功呢??"+b2);

        //4.再创建一个File对象
        File ff2 = new File("aaa\\bbb\\ccc\\ddd");
        boolean b3 = ff2.mkdir();
        System.out.println("是否创建成功呢??"+b3);

        boolean b4 = ff2.mkdirs();
        System.out.println("是否创建成功呢??"+b4);

        //5.再创建File对象
        File ff3 = new File("2.txt");
        boolean b5 = ff3.delete();
        System.out.println("是否删除成功呢??"+b5);
    }
}    
    
注意: a.mkdir和mkdirs的区别
      b.delete方法要么删除文件,要么删除空文件夹,不能删除非空文件夹    
7.File类遍历目录的方法
public String[] list(); 列出当前文件夹下所有直接的文件和文件夹的名字
public File[] listFiles();列出当前文件夹下所有直接的文件和文件夹的File对象
    
public class FileDemo06 {
    public static void main(String[] args) {
        //1.创建一个File对象,必须是一个文件夹
        File ff = new File("C:\\Users\\Administrator\\Desktop\\temp\\aaa");
        //2.list
        String[] filenames = ff.list();
        for (String filename : filenames) {
            System.out.println(filename);
        }
        //3.listFiles
        File[] files = ff.listFiles();
        for (File file : files) {
            System.out.println(file);
        }
    }
}
注意: list和listFiles只能列直接的子文件或者子文件夹    

二.递归

1.什么是递归?
递归不是Java语言独有的,(基本上很多语言都可以递归)
递归就是:在方法中调用该方法本身(自己调自己)
public class RecursionDemo01 {
    public static void main(String[] args) {
        method();
    }

    public static void method(){
        System.out.println("method....");
        //调用Method自己,这里称为递归
        method();
    }
}

无限递归(死递归)出现这个错误: StackOverflowError 栈溢出错误!!!

在这里插入图片描述

如果要使用递归,必须保证递归有出口(结束的条件)
    public static void main(String[] args) {
        method1(10);
    }

    //正常递归(有出口)
    public static void method1(int n){
        //判断
        if (n == 0){
            return; //这里就是递归的出口
        }
        System.out.println("method1...."+n);
        //调用Method自己
        method1(n-1);
    }
注意: 就算递归有出口,还要保证递归在运行到出口之前次数不能太多(太多也会栈内存溢出)

2.递归求和案例
需求: 使用递归求1-n的和(开发中不要用递归求和)

使用递归三大步骤:
	a.先定义一个方法(求和)
    b.找规律,调用自己
    c.让递归有出口(结束的条件)       
public class RecursionDemo02 {
    public static void main(String[] args) {
        //需求: 使用递归求1-n的和(开发中不要用递归求和)
        int sum = getSum(100);
        System.out.println(sum);
    }
    //使用递归
    //a.先定义一个方法(求和)
    public static int getSum(int n){
        //c.让递归有出口(结束的条件)
        if (n == 1){
            return 1;
        }
        //b.找规律,调用自己
        // 1+2+3..n = (1+2+3..+n-1) + n
        // getSum(n) = getSum(n-1) + n
        return getSum(n-1) + n;
    }


    //使用循环
    public static int getSum1(int n){
        //求和
        int sum = 0;
        for (int i = 1; i < n+1; i++) {
            sum+=i;
        }
        return sum;
    }
}    

在这里插入图片描述

3.递归求阶乘案例
需求: 使用递归求n的阶乘(就是求1-n的积)(开发中不要用递归求积)

使用递归三大步骤:
	a.先定义一个方法(求积)
    b.找规律,调用自己
    c.让递归有出口(结束的条件) 
        
public class RecursionDemo03 {
    public static void main(String[] args) {
        //需求: 使用递归求n的阶乘(就是求1-n的积)(开发中不要用递归求和)
        int ji = getJi(4);
        System.out.println(ji);
    }
    //使用递归三大步骤:
    //a.先定义一个方法(求积)
    public static int getJi(int n){
        //c.让递归有出口(结束的条件)
        if (n == 1) {
            return 1;
        }
        //b.找规律,调用自己
        // 1*2*3..*n = (1*2*3..n-1)*n
        // getJi(n) = getJi(n-1)*n
        return getJi(n-1)*n;
    }
    //使用循环
    public static int getJi1(int n){
        int ji = 1;
        for (int i = 1; i < n+1; i++) {
            ji *= i;
        }
        return ji;
    }
}        

4.文件搜索案例
需求:
	在某个目录中找出所有的.txt文件
    某个目录:C:\Users\Administrator\Desktop\temp\aaa

public class RecursionDemo04 {
    public static void main(String[] args) {
//        需求:
//        在某个目录中找出所有的.txt文件
//        某个目录:C:\Users\Administrator\Desktop\temp\aaa
        File fileDir = new File("C:\\Users\\Administrator\\Desktop\\temp\\aaa");
        //调用
        findTxtFile(fileDir);
    }

    //从指定的目录中搜索txt文件
    public static void findTxtFile(File file) {
        //1.列出该文件夹下所有的File对象
        File[] files = file.listFiles();
        //2.遍历列出的数组
        for (File f : files) {
            //3.判断是否为txt文件
            if (f.getName().endsWith(".txt") && f.isFile()) {
                System.out.println(f);
            }else if (f.isDirectory()){
                //那么列出这个f文件夹下的所有.txt文件即可
                findTxtFile(f); // 递归!!!
            }
        }
    }
}               

三.IO流的概述

1.什么是IO流
I: Input 输入流, 数据从外部设备到程序中,读数据的流
O: Output 输出流, 数据从程序到外部设备,写数据的流
流: 一种比喻,数据传输的过程比喻成流

在这里插入图片描述

2.IO流的分类
a.根据流的方向分类:
	输入流
    输出流
b.根据流中操作的数据类型分类:
	字节流 byte 
    字符流 char  
以上两种分类我们可以综合一下:
	字节输入流
    字节输出流
        
    字符输入流
    字符输出流           

3.Java中IO的四大流
字节输入流: InputStream(顶层父类,抽象类)
    
字节输出流: OutputStream(顶层父类,抽象类)
    
字符输入流: Reader(顶层父类,抽象类) 
    
字符输出流 :Writer(顶层父类,抽象类)   
    
技巧: Java中所有的流都会是以上四个流中某一个的子类
    	而且具体的流的命名是非常有规范的!!
    		规范: 功能名 +父类名
                
      比如:FileWriter 向文件中写出字符为单位的数据  
      比如:FileInputStream 从文件读取以字节为单位的数据    

四.字节流

1.万物皆对象和IO流一切皆字节
万物皆对象思想: 现实生活中的任何东西,我们在Java中都可以使用一个对象来表示
IO流中一切皆字节: 我们电脑所有的数据,最终都是由字节组成的(01010101二进制组成)
    普通文本文件,图片文件,视频文件,都是字节组成的吗??  是的!!!
    为什么我打开这些文件看到不是01010101这些数据??? 因为我们打开这些文件使用的软件帮助我们解析了
    能不能打开这文件时不要解析,就要看到0101??? 可以 使用二进制查看软件,BinaryViewer   

2.字节输出流
顶层父类: OutputStream(抽象类)
共性方法:
	public void close(); 关闭此流,释放资源
    public void flush(); 刷新缓冲区(目前没有!!)
       
    public void write(int b); //一次写一个字节  
	public void write(byte[] bs);//一次写一个字节数组
	public void write(byte[] bs,int startIndex,int len);//一次写一个字节数组的一部分

3.FileOutputStream类的使用
文件的字节输出流(向文件中写字节数据的)

  • a.构造方法

    public FileOutputStream(String path);//必须传入文件的路径
    public FileOutputStream(File file);//必须传入文件的File对象
    
    public class FileOutputStreamDemo03 {
        public static void main(String[] args) throws FileNotFoundException {
            //1.创建一个FileOutputStream
            FileOutputStream fos = new FileOutputStream("1.txt");
    //        FileOutputStream fos = new FileOutputStream(new File("1.txt"));
            /**
             * 构造方法干了三件事!!!
             * a.创建对象fos
             * b.判断文件是否存在
             *      如果存在,会清空文件的内容
             *      如果不存在,会自动创建该文件
             * c.让对象fos和1.txt绑定     
             */
        }
    }
    
    
  • b.写字节数据的三个方法

    public class FileOutputStreamDemo02 {
        public static void main(String[] args) throws IOException {
            //1.创建一个FileOutputStream
            FileOutputStream fos = new FileOutputStream("1.txt");
            //2.向文件中写数据
            //a.写一个字节
            fos.write(97); // a
            //思考:我想要打开之后看到97,怎么办???
    //        fos.write(57); // 9
    //        fos.write(55); // 7
            //b.写一个字节数组
            byte[] bs = {97,98,99,100};
            fos.write(bs);
            //思考:我想要打开之后看到HelloWorldJavafghjktyuivnm
    //        byte[] bs1 = "HelloWorldJavafghjktyuivnm".getBytes();
    //        fos.write(bs1);
            //c.写一个字节数组的一部分
            byte[] bs2 = {97,98,99,100};
            fos.write(bs2,1,2);
        }
    }
    
    
  • c.如何追加续写

    非常简单!!!!!!只要使用以下构造即可
        public FileOutputStream(String path,boolean append);//append表示是否追加
    	public FileOutputStream(File file,boolean append);//append表示是否追加
    
    public class FileOutputStreamDemo03 {
        public static void main(String[] args) throws IOException {
            //1.创建一个FileOutputStream
            FileOutputStream fos = new FileOutputStream("1.txt",true);
            //2.写数据
            fos.write(97);
        }
    }
    
    
  • d.如何换行

    非常简单!!!!只要写文件中写一个代表换行的符号即可
        windows \r\n
        Linux   \n
        MacOS	\r   (MacOSX 也是 \n)
    
    public class FileOutputStreamDemo04 {
        public static void main(String[] args) throws IOException {
            //1.创建一个FileOutputStream
            FileOutputStream fos = new FileOutputStream("1.txt");
    
            //2.写数据
            for (int i = 0; i < 10; i++) {
                fos.write("java\r\n".getBytes());
    //            fos.write("\r\n".getBytes());
            }
        }
    }    
    
    
  • close和flush
    public void flush(); 目前我们没用!!(对于字节流输出流没用!!)
        
    public void close(); 关闭流,释放资源
        流一旦使用完毕,及时释放资源,别的程序就可以使用该资源了!!!
    
    
4.字节输入流
顶层父类: InputStream(抽象类)
共性方法:
	public void close();// 关闭流,释放资源

	public int read(); //一次读一个字节
	public int read(byte[] bs);//一次读取一个字节数组,返回值表示实际读取的字节个数

5.FileInputStream类的使用
文件的字节输入流(从文件中读取以字节为单位的数据)

  • a.构造方法

    public FileInputStream(String path);//传入文件的路径
    public FileInputStream(File file);//传入文件的File对象
    
    public class FileInputStreamDemo01 {
        public static void main(String[] args) throws Exception {
            //1.创建FileInputStream对象
            FileInputStream fis = new FileInputStream("1.txt");
    //        FileInputStream fis = new FileInputStream(new File("1.txt"));
            /**
             * 以上构造方法干了三件事!!!
             * a.创建对象fis
             * b.判断文件是否存在
             *      如果存在,什么不干(不清空!!!)
             *      如果不存在,会直接抛出异常FileNotFoundException
             * c.让fis和1.txt绑定
             */
        }
    }
    
    
  • b.读取一个字节【重点,三遍】

    public class FileInputStreamDemo02 {
        public static void main(String[] args) throws Exception {
            //1.创建FileInputStream对象
            FileInputStream fis = new FileInputStream("1.txt");
            //2.读数据
            //a.一次读取一个字节
            //int b = fis.read();
            //System.out.println((char) b);
            //==============一次读取一个字节的标准循环代码==================
            int b = 0;//保存读取到字节
            /**
             * (b = fis.read()) != -1
             * 这句代码干了三件事!!!
             * a.先读  fis.read()
             * b.赋值  b = 读取字节
             * c.判断  b != -1
             */
            while ((b = fis.read()) != -1) {
                System.out.println((char) b);
            }
            //4.释放资源
            fis.close();
        }
    }
    
    
  • c.读取一个字节数组【重点,三遍】

    public class FileInputStreamDemo03 {
        public static void main(String[] args) throws Exception {
            //1.创建FileInputStream对象
            FileInputStream fis = new FileInputStream("1.txt");
            //2.读数据
            //b.一次读取一个字节数组
            //byte[] bs = new byte[4]; //实际开发中 一般1024 或者 其整数倍
            //int len = fis.read(bs);
            //System.out.println("实际读取到"+len+"个字节");
            //System.out.println(new String(bs,0,len));
            //===============一次读取一个字节数组的标准循环代码===============
            byte[] bs = new byte[4];
            int len = 0;
            /**
             * (len = fis.read(bs)) != -1
             * 以上代码干了三件事
             * a.先读  fis.read(bs)
             * b.赋值  len = 实际读取的个数
             * c.判断  len != -1
             */
            while ((len = fis.read(bs)) != -1) {
                System.out.println(new String(bs,0,len));
            }
            //3.释放资源
            fis.close();
        }
    }
    
    

在这里插入图片描述

6.字节流练习:复制图片【重点,三遍】
  • a.复制文件的过程(画图)

在这里插入图片描述

  • b.代码实现(代码演示)
public class CopyFileDemo {
    public static void main(String[] args) throws Exception {
        //复制文件
        //1.源文件G:\uplaod\1.png
        FileInputStream fis = new FileInputStream("G:\\upload\\1.png");
        //2.目标文件
        FileOutputStream fos = new FileOutputStream("copy.png");
        //3.复制文件(一次赋值一个字节数组)
        byte[] bs = new byte[1024]; // 1KB
        int len = 0;
        while ((len = fis.read(bs)) != -1) {
            fos.write(bs,0,len); // 为了防止最后一次读取时 写入多余的数据
        }
        //4.释放资源(先开后关)
        fos.close();
        fis.close();
    }
}

总结:
能够说出File对象的创建方式
    public File(String path);
	public File(String parent,String child);	
	public File(File file,String child);	
能够使用File类常用方法
    获取方法 getPath getAbsolutepath getName length
    判断方法 exists isFile isDirectory
    创建方法 createNewFile mkdir mkdirs
    删除方法 delete 
能够遍历文件夹
    遍历文件夹方法 list listFiles
能够辨别相对路径和绝对路径【重点】
    绝对路径: 以盘符开头的路径 C:\\windows\\data\\1.txt
    相对路径: 相当于当前项目的根目录 1.txt 表示 当前项目根目录下的1.txt
   
能够解释递归的含义
    方法内部调用方法本身(自己调自己)    
能够使用递归的方式计算5的阶乘(了解)
能够说出使用递归会内存溢出隐患的原因
    递归不断调用方法,方法不断入栈,栈内存就会溢出!!!     
能够说出IO流的分类和功能
   输入流 : 读数据
   输出流 : 写数据   
       
   字节流 : 数据是以字节为单位
   字符流 : 数据是以字符为单位
       
能够使用字节输出流写出数据到文件
       FileOutputStream类
       		write(int b);
			write(byte[] bs);
			write(byte[] bs,int startIndex,int len);
能够使用字节输入流读取数据到程序
    	FileInputStream类
    		int read();
			int read(byte[] bs);
能够理解读取数据read(byte[])方法的原理【掌握】
能够使用字节流完成文件的复制【一个一个字节复制,一个一个字节数组复制,今天最最最最重要的,3遍】

发布了23 篇原创文章 · 获赞 0 · 访问量 1137

猜你喜欢

转载自blog.csdn.net/qq_44845814/article/details/104995592