全球疫情不断严重的时期
我的Java学习并没有落下
好几天没更新有点不适应
今天我们继续学习,继续加油!
目录
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文件
分析:
-
目录搜索,无法判断多少级目录,所以使用递归,遍历所有目录。
-
遍历目录时,获取的子文件,通过文件名称,判断是否符合条件。
代码实现:搜索 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);
}
}
}
}
改进:
-
接口作为参数,需要传递子类对象,重写其中方法。选择匿名内部类方式,比较简单。
-
accept
方法,参数为File
,表示当前File
下所有的子文件和子目录。保留住则返回true,过滤掉则返回false。保留规则:-
要么是
.java
文件。 -
要么是目录,用于继续遍历。
-
-
通过过滤器的作用,
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)
:从字节输入流中读取键值对。
欢迎关注博主,欢迎互粉,一起学习!
感谢您的阅读,不足之处欢迎指正!