Java从入门到高级(第四天)


全球疫情不断严重的时期

我的Java学习并没有落下

好几天没更新有点不适应

今天我们继续学习,继续加油!


目录

1. File类

1.1 获取功能的方法

1.2 绝对路径和相对路径

1.3 判断功能的方法

1.4 创建删除功能的方法

1.5 目录的遍历

1.6 文件或者文件夹的判断

2. 递归

2.1 递归实现的举例

2.2 搜素.java文件

3. I/O

3.1 IO的分类

4. 字节流

4.1 OutputStream字节输出流

4.2 FileOutputStream类

4.3 InputStream字节输入流

4.4 FileInputStream类

5. 字符流

5.1 Reader字符输入流

5.2 FileReader类

5.3 Writer字符输出流

5.4 FileWriter类

6. IO异常的处理

7. 属性集

7.1 Properties类


1. File类

 java.io.File 类是文件和目录路径名的抽象表示,主要用于文件和目录的创建、查找和删除等操作。

构造方法:

  •  public File(String pathname) :通过将给定的路径名字符串转换为抽象路径名来创建新的 File 实例。

  •  public File(String parent, String child) :从父路径名字符串和子路径名字符串创建新的 File 实例。

  •  public File(File parent, String child) :从父抽象路径名和子路径名字符串创建新的 File 实例。


1.1 获取功能的方法

  •  public String getAbsolutePath() :返回此 File 的绝对路径名字符串。

  •  public String getPath() :将此 File 转换为路径名字符串。

  •  public String getName() :返回由此 File 表示的文件或目录的名称。

  •  public long length() :返回由此 File 表示的文件的长度。


1.2 绝对路径和相对路径

  • 绝对路径:从盘符开始的路径,这是一个完整的路径。

  • 相对路径:相对于项目目录的路径,这是一个便捷的路径,开发中经常使用相对路径。


1.3 判断功能的方法

  •  public boolean exists() :此 File 表示的文件或目录是否实际存在。

  •  public boolean isDirectory() :此 File 表示的是否为目录。

  •  public boolean isFile() :此 File 表示的是否为文件。


1.4 创建删除功能的方法

  •  public boolean createNewFile() :当且仅当具有该名称的文件尚不存在时,创建一个新的空文件。

  •  public boolean delete() :删除由此 File 表示的文件或目录。

  •  public boolean mkdir() :创建由此 File 表示的目录。

  •  public boolean mkdirs() :创建由此 File 表示的目录,包括任何必需但不存在的父目录。


1.5 目录的遍历

  •  public String[] list() :返回一个 String 数组,表示该 File 目录中的所有子文件或目录。

  •  public File[] listFiles() :返回一个 File 数组,表示该 File 目录中的所有的子文件或目录。

代码实现:获取当前目录下的文件以及文件夹的名称。

public class FileFor {
    public static void main(String[] args) {
        File dir = new File("d:\\java_projects");
      
      	// 获取当前目录下文件以及文件夹的名称
	String[] names = dir.list();
	for(String name : names){
		System.out.println(name);
	}
        
        // 获取当前目录的文件以及文件夹的完整路径名称
        File[] files = dir.listFiles();
        for (File file : files) {
            System.out.println(file);
        }
    }
}

1.6 文件或者文件夹的判断

判断 File 对象是否是文件,是文件则输出:xxx是一个文件,否则输出:xxx不是一个文件。判断 File 对象是否是文件夹,是文件夹则输出:xxx是一个文件夹,否则输出:xxx不是一个文件夹。

代码实现:文件或者文件夹的判断。

public class Test01 {
	public static void main(String[] args) {
		// 创建文件对象
		File f1 = new File("d:\\a.txt");
		
                // 判断是否是一个文件
		if(f1.isFile()) {
			System.out.println(f1.getName()+"是一个文件");
		}  else {
			System.out.println(f1.getName()+"不是一个文件");
		}
		
                // 创建文件对象
		File f2 = new File("d:\\aa");
		
                // 判断是否是一个文件夹
		if(f2.isDirectory()) {
			System.out.println(f2.getName()+"是一个文件夹");
		}  else {
			System.out.println(f2.getName()+"不是一个文件夹");
		}
	}
}

2. 递归

递归:指在当前方法内调用自己的这种现象。

递归的分类:

  • 递归分为两种,直接递归和间接递归。

  • 直接递归称为方法自身调用自己。

  • 间接递归可以A方法调用B方法,B方法调用C方法,C方法调用A方法。

注意事项

  • 递归一定要有条件限定,保证递归能够停止下来,否则会发生栈内存溢出。

  • 在递归中虽然有限定条件,但是递归次数不能太多。否则也会发生栈内存溢出。

  • 构造方法:禁止递归。


2.1 递归实现的举例

代码实现:计算1 ~ n的和。

public class DiGuiDemo01 {
    public static void main(String[] args) {
	// 计算1~num的和,使用递归完成
	int num = 10;
      	
        // 调用求和的方法
	int sum = getSum(num);
      	System.out.println(sum);
		
    }
  	
    // 通过递归算法实现
    public static int getSum(int num) {
      	// num为1时,方法返回1,
      	if(num == 1){
	    return 1;
	}

      	// num不为1时,方法返回 num +(num-1)的累和
	return num + getSum(num-1);
    }
}

代码实现:递归求阶乘。

public class DiGuiDemo02 {
    // 计算n的阶乘,使用递归完成
    public static void main(String[] args) {
        int n = 10;
      	
        // 调用求阶乘的方法
        int value = getValue(n);
        System.out.println("阶乘为:"+ value);
    }

    // 通过递归算法实现。
    public static int getValue(int n) {
        if (n == 1) {
            return 1;
        }
      	
        // 不为1则递归
        return n * getValue(n - 1);
    }
}

代码实现:递归打印多级目录。

public class DiGuiDemo03 {
    public static void main(String[] args) {
      	// 创建File对象
        File dir = new File("D:\\aaa");
      	
        // 调用打印目录方法
        printDir(dir);
    }

    public static void printDir(File dir) {
      	// 获取子文件和目录
        File[] files = dir.listFiles();
      	
        // 循环打印
        for (File file : files) {
            if (file.isFile()) {
              	// 是文件,输出文件绝对路径
                System.out.println("文件名:"+ file.getAbsolutePath());
            } else {
              	// 是目录,输出目录绝对路径
                System.out.println("目录:"+file.getAbsolutePath());
              	
                // 继续遍历,调用printDir,形成递归
                printDir(file);
            }
        }
    }
}

2.2 搜素.java文件

分析

  1. 目录搜索,无法判断多少级目录,所以使用递归,遍历所有目录。

  2. 遍历目录时,获取的子文件,通过文件名称,判断是否符合条件。

代码实现:搜索 D:\aaa 目录中的 .java 文件。

public class DiGuiDemo01 {
    public static void main(String[] args) {
        // 创建File对象
        File dir  = new File("D:\\aaa");
      	
        // 调用打印目录方法
        printDir(dir);
    }

    public static void printDir(File dir) {
      	// 获取子文件和目录
        File[] files = dir.listFiles();
      	
      	// 循环打印
        for (File file : files) {
            if (file.isFile()) {
              	// 是文件,判断文件名并输出文件绝对路径
                if (file.getName().endsWith(".java")) {
                    System.out.println("文件名:" + file.getAbsolutePath());
                }
            } else {
                // 是目录,继续遍历
                printDir(file);
            }
        }
    }
}

改进:

  1. 接口作为参数,需要传递子类对象,重写其中方法。选择匿名内部类方式,比较简单。

  2.  accept 方法,参数为 File ,表示当前 File 下所有的子文件和子目录。保留住则返回true,过滤掉则返回false。保留规则:

    1. 要么是 .java 文件。

    2. 要么是目录,用于继续遍历。

  3. 通过过滤器的作用, listFiles(FileFilter) 返回的数组元素中,子文件对象都是符合条件的,可以直接打印。

 java.io.FileFilter 是一个接口,是 File 的过滤器。 该接口的对象可以传递给 File 类的 listFiles(FileFilter) 作为参数, 接口中只有一个方法。

 boolean accept(File pathname) :测试 pathname 是否应该包含在当前 File 目录中,符合则返回true

代码实现:搜索 D:\aaa 目录中的 .java 文件。 (实现文件过滤器优化)

public class DiGuiDemo02 {
    public static void main(String[] args) {
        File dir = new File("D:\\aaa");
        printDir2(dir);
    }
  
    public static void printDir2(File dir) {
      	// 匿名内部类方式,创建过滤器子类对象
        File[] files = dir.listFiles(new FileFilter() {
            @Override
            public boolean accept(File pathname) {
                return pathname.getName().endsWith(".java") || pathname.isDirectory();
            }
        });
      	
        // 循环打印
        for (File file : files) {
            if (file.isFile()) {
                System.out.println("文件名:" + file.getAbsolutePath());
            } else {
                printDir2(file);
            }
        }
    }
}  

优化:

  FileFilter 是只有一个方法的接口,因此可以用Lambda表达式简写。

代码实现:搜索 D:\aaa 目录中的 .java 文件。 (实现Lambda优化)

public static void printDir3(File dir) {
    // lambda的优化
    File[] files = dir.listFiles(f -> f.getName().endsWith(".java") || f.isDirectory());
  	
    // 循环打印
    for (File file : files) {
        if (file.isFile()) {
            System.out.println("文件名:" + file.getAbsolutePath());
      	} else {
        	printDir3(file);
      	}
    }
}

3. I/O

数据的传输,可以看做是一种数据的流动,按照流动的方向,以内存为基准,分为输入 input 输出 output ,即流向内存是输入流,流出内存的输出流。

Java中I/O操作主要是指使用 java.io 包下的内容,进行输入、输出操作。输入也叫做读取数据,输出也叫做作写出数据。


3.1 IO的分类

根据数据的流向分为:输入流输出流

  • 输入流 :把数据从其他设备上读取到内存中的流。

  • 输出流 :把数据从内存 中写出到其他设备上的流。

格局数据的类型分为:字节流字符流

  • 字节流 :以字节为单位,读写数据的流。

  • 字符流 :以字符为单位,读写数据的流。

 输入流输出流
字节流字节输入流 InputStream字节输出流 OutputStream
字符流字符输入流 Reader字符输出流 Writer

4. 字节流

一切文件数据(文本、图片、视频等)在存储时,都是以二进制数字的形式保存,都一个一个的字节,那么传输时一样如此。所以,字节流可以传输任意文件数据。在操作流的时候,我们要时刻明确,无论使用什么样的流对象,底层传输的始终为二进制数据。


4.1 OutputStream字节输出流

 java.io.OutputStream 抽象类是表示字节输出流的所有类的超类,将指定的字节信息写出到目的地。它定义了字节输出流的基本共性功能方法。

  •  public void close() :关闭此输出流并释放与此流相关联的任何系统资源。

  •  public void flush() :刷新此输出流并强制任何缓冲的输出字节被写出。

  •  public void write(byte[] b) :将 b.length 字节从指定的字节数组写入此输出流。

  •  public void write(byte[] b, int off, int len) :从指定的字节数组写入 len 字节,从偏移量 off 开始输出到此输出流。

  •  public abstract void write(int b) :将指定的字节输出流。


4.2 FileOutputStream类

 OutputStream 有很多子类,我们从最简单的一个子类开始。

 java.io.FileOutputStream 类是文件输出流,用于将数据写出到文件。

构造方法:

  •  public FileOutputStream(File file) :创建文件输出流以写入由指定的 File 对象表示的文件。

  •  public FileOutputStream(String name) :创建文件输出流以指定的名称写入文件。

  •  public FileOutputStream(File file, boolean append) :创建文件输出流以写入由指定的 File 对象表示的文件。

  •  public FileOutputStream(String name, boolean append) :创建文件输出流以指定的名称写入文件。

代码实现:写入字节、数据追加写入、写入换行

// 写入字节举例
public class FOSWrite {
    public static void main(String[] args) throws IOException {
        // 使用文件名称创建流对象
        FileOutputStream fos = new FileOutputStream("fos.txt");     
      	
        // 写入3个字节
      	fos.write(97); 
      	fos.write(98); 
      	fos.write(99); 

        // 关闭资源
        fos.close();
    }
}

// 数据追加续写举例
public class FOSWrite {
    public static void main(String[] args) throws IOException {
        // 使用文件名称创建流对象
        FileOutputStream fos = new FileOutputStream("fos.txt",true);     
      	
        // 字符串转换为字节数组
      	byte[] b = "abcde".getBytes();
	
        // 写出从索引2开始,2个字节。索引2是c,两个字节,也就是cd
        fos.write(b);
      	
        // 关闭资源
        fos.close();
    }
}

// 写出换行举例
public class FOSWrite {
    public static void main(String[] args) throws IOException {
        // 使用文件名称创建流对象
        FileOutputStream fos = new FileOutputStream("fos.txt");  
      	
        // 定义字节数组
      	byte[] words = {97,98,99,100,101};
      	
        // 遍历数组
        for (int i = 0; i < words.length; i++) {
            // 写出一个字节
            fos.write(words[i]);
            // 写出一个换行
            fos.write("\r\n".getBytes());
        }
      	// 关闭资源
        fos.close();
    }
}

回车符 \r 和换行符 \n

  • 回车符:回到一行的开头(return)。

  • 换行符:下一行(newline)。

系统中的换行:

  • Windows系统里,每行结尾是 回车+换行 ,即 \r\n

  • Unix系统里,每行结尾只有 换行 ,即 \n

  • Mac系统里,每行结尾是 回车 ,即 \r 。从 Mac OS X开始与Linux统一。


4.3 InputStream字节输入流

 java.io.InputStream 抽象类是表示字节输入流的所有类的超类,可以读取字节信息到内存中。它定义了字节输入流的基本共性功能方法。

  •  public void close() :关闭此输入流并释放与此流相关联的任何系统资源。

  •  public abstract int read() :从输入流读取数据的下一个字节。

  •  public int read(byte[] b) :从输入流中读取一些字节数,并将它们存储到字节数组b中 。


4.4 FileInputStream类

 java.io.FileInputStream 类是文件输入流,从文件中读取字节。

构造方法:

  •  FileInputStream(File file) :通过打开与实际文件的连接来创建一个 FileInputStream ,该文件由文件系统中的 File 对象 file 命名。

  •  FileInputStream(String name) :通过打开与实际文件的连接来创建一个 FileInputStream ,该文件由文件系统中的路径名 name 命名。

当你创建一个流对象时,必须传入一个文件路径。该路径下,如果没有该文件,会抛出 FileNotFoundException

代码实现:复制图片

public class Copy {
    public static void main(String[] args) throws IOException {
        // 创建流对象
        FileInputStream fis = new FileInputStream("D:\\test.jpg");
        
        // 指定目的地
        FileOutputStream fos = new FileOutputStream("test_copy.jpg");

        // 定义数组和长度
        byte[] b = new byte[1024];
        int len;
        
        // 循环读取
        while ((len = fis.read(b))!=-1) {
            // 写出数据
            fos.write(b, 0 , len);
        }

        // 关闭资源
        fos.close();
        fis.close();
    }
}

5. 字符流

当使用字节流读取文本文件时,可能会有一个小问题。就是遇到中文字符时,可能不会显示完整的字符,那是因为一个中文字符可能占用多个字节存储。所以Java提供一些字符流类,以字符为单位读写数据,专门用于处理文本文件。


5.1 Reader字符输入流

 java.io.Reader 抽象类是表示用于读取字符流的所有类的超类,可以读取字符信息到内存中。它定义了字符输入流的基本共性功能方法。

  •  public void close() :关闭此流并释放与此流相关联的任何系统资源。

  •  public int read() :从输入流读取一个字符。

  •  public int read(char[] cbuf) :从输入流中读取一些字符,并将它们存储到字符数组 cbuf 中 。


5.2 FileReader类

 java.io.FileReader 类是读取字符文件的便利类。构造时使用系统默认的字符编码和默认字节缓冲区。

构造方法:

  •  FileReader(File file) :创建一个新的 FileReader ,给定要读取的 File 对象。

  •  FileReader(String fileName) :创建一个新的 FileReader ,给定要读取的文件的名称。

当你创建一个流对象时,必须传入一个文件路径。类似于 FileInputStream

代码实现:读取字符、字符数组

// 读取字符数据举例
public class FRRead {
    public static void main(String[] args) throws IOException {
      	// 使用文件名称创建流对象
       	FileReader fr = new FileReader("read.txt");
        int b ;
        
        // 循环读取
        while ((b = fr.read())!=-1) {
            System.out.println((char)b);
        }
	// 关闭资源
        fr.close();
    }
}

// 使用字符数组读取
public class FRRead {
    public static void main(String[] args) throws IOException {
      	// 使用文件名称创建流对象
       	FileReader fr = new FileReader("read.txt");
        int len ;
        
        // 定义字符数组,作为装字符数据的容器
        char[] cbuf = new char[2];
        
        // 循环读取
        while ((len = fr.read(cbuf))!=-1) {
            System.out.println(new String(cbuf));
        }
	// 关闭资源
        fr.close();
    }
}

5.3 Writer字符输出流

 java.io.Writer 抽象类是表示用于写出字符流的所有类的超类,将指定的字符信息写出到目的地。它定义了字节输出流的基本共性功能方法。

  •  void write(int c) :写入单个字符。

  •  void write(char[] cbuf) :写入字符数组。

  •  abstract void write(char[] cbuf, int off, int len) :写入字符数组的某一部分, off 数组的开始索引, len 写的字符个数。

  •  void write(String str) :写入字符串。

  •  void write(String str, int off, int len) :写入字符串的某一部分, off 字符串的开始索引, len 写的字符个数。

  •  void flush() :刷新该流的缓冲。

  •  void close() :关闭此流,但要先刷新它。


5.4 FileWriter类

 java.io.FileWriter 类是写出字符到文件的便利类。构造时使用系统默认的字符编码和默认字节缓冲区。

构造方法:

  •  FileWriter(File file) :创建一个新的 FileWriter ,给定要读取的File对象。

  •  FileWriter(String fileName) :创建一个新的 FileWriter ,给定要读取的文件的名称。

当你创建一个流对象时,必须传入一个文件路径,类似于 FileOutputStream

代码实现:写出字符、写出其他数据、续写和换行

// 写出字符举例
public class FWWrite {
    public static void main(String[] args) throws IOException {
        // 使用文件名称创建流对象
        FileWriter fw = new FileWriter("fw.txt");     
      	
        // 写出4个字符
      	fw.write(97); 
      	fw.write('b'); 
      	fw.write('C'); 
      	fw.write(30000); 
      
        // 关闭资源
        fw.close();
    }
}

// 写出字符数组
public class FWWrite {
    public static void main(String[] args) throws IOException {
        // 使用文件名称创建流对象
        FileWriter fw = new FileWriter("fw.txt");     
      	
        // 字符串转换为字节数组
      	char[] chars = "玩家1和玩家2".toCharArray();
      
      	// 写出字符数组
      	fw.write(chars);
        
	// 写出从索引2开始,2个字节。
        fw.write(b,2,2);
      
      	// 关闭资源
        fos.close();
    }
}

// 续写和换行
public class FWWrite {
    public static void main(String[] args) throws IOException {
        // 使用文件名称创建流对象,可以续写数据
        FileWriter fw = new FileWriter("fw.txt",true);     
      	
        // 写出字符串
        fw.write("玩家1");
      	
        // 写出换行
      	fw.write("\r\n");
      	
        // 写出字符串
  	fw.write("玩家2");
      	
        // 关闭资源
        fw.close();
    }
}

6. IO异常的处理

可以使用JDK7优化后的 try-with-resource 语句,该语句确保了每个资源在语句结束时关闭。所谓的资源(resource)是指在程序完成后,必须关闭的对象。

格式:

try (创建流对象语句,如果多个,使用';'隔开) {
    // 读写数据
} catch (IOException e) {
    e.printStackTrace();
}

JDK9 try-with-resource 的改进,对于引入对象的方式,支持的更加简洁。被引入的对象,同样可以自动关闭,无需手动close。

格式:

// 被final修饰的对象
final Resource resource1 = new Resource("resource1");
// 普通对象
Resource resource2 = new Resource("resource2");

// 引入方式:直接引入
try (resource1; resource2) {
     // 使用对象
}


7. 属性集

 java.util.Properties 继承于 Hashtable ,来表示一个持久的属性集。它使用键值结构存储数据,每个键及其对应值都是一个字符串。该类也被许多Java类使用,比如获取系统属性时, System.getProperties 方法就是返回一个 Properties 对象。


7.1 Properties类

  •  public Properties() :创建一个空的属性列表。

  •  public Object setProperty(String key, String value) :保存一对属性。

  •  public String getProperty(String key) :使用此属性列表中指定的键搜索属性值。

  •  public Set<String> stringPropertyNames() :所有键的名称的集合。

  •  public void load(InputStream inStream) :从字节输入流中读取键值对。


 

欢迎关注博主,欢迎互粉,一起学习!

感谢您的阅读,不足之处欢迎指正!

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值