一、递归
递归 方法直接或间接的调用自己 注意 递归如果没有控制好终止,会出现递归死循环,导致栈内存溢出错误。
案例 计算n的阶乘 阶乘 5! = 5 * 4 * 3 * 2 * 1 4! = 4 * 3 * 2 * 1 3! = 3 * 2 * 1 2! = 2 * 1 1! = 1 n! = n * (n-1) * (n-2) *.....* 1 公式 f(n) = f(n-1) * n
public class Demo2 {
public static void main(String[] args) {
System.out.println(fun(5));
}
public static int fun(int n){
if(n == 1){
return 1;
}else{
return fun(n-1) * n;
}
}
}
二、File
2.1 创建对象
File 可以表示文件,也可以表示文件夹,联的路径可以存在,也可以不存在 创建对象 File(String pathname) 根据指定路径创建File对象 File(String parent,String child) 跟进指定参数拼接的路径创建File对象 File(File parent,String child) 跟进指定参数拼接的路径创建File对象 文件路径分隔符写法 1、/可以单独写 2、|需要转义 3、File.separator根据系统自动匹配分隔符 路径的分类 绝对路径:从盘符开始的路径 相对路径:不带盘符,默认直接到当前工程下的目录寻找文件。
2.2 常用方法1:判断文件类型、获取文件信息
常用方法1:判断文件类型、获取文件信息 boolean exists() 判断文件路径是否存在 boolean isFile() 判断是否是文件(不存在的都是false) boolean isDirectory() 判断是否是文件夹(不存在的都是false) String getName() 获取文件/文件名,包含后缀 long length() 获取文件大小,返回字节个数 long lastModified() 获取最后修改时间 string getPath() 获取创建对象时的路径 String getAbsolutePath() 获取对象绝对路名
public class Demo2 {
public static void main(String[] args) {
File f1 = new File("day08-code/test1");//文件夹-已存在
File f2 = new File("day08-code/test1/1.txt");//文件-已存在
File f3 = new File("day08-code/test2");//文件夹-不存在
File f4 = new File("day08-code/test2/2.txt");//文件-不存在
//boolean exists() 判断文件路径是否存在
boolean exists1 = f1.exists();
System.out.println("f1:" + exists1);//true
boolean exists3 = f3.exists();
System.out.println("f3:" + exists3);//false
//boolean isFile() 判断是否是文件
boolean file2 = f2.isFile();
System.out.println("f2:" + file2);//true
boolean file4 = f4.isFile();
System.out.println("f4:" + file4);//false
//boolean isDirectory() 判断是否是文件夹
boolean dir1 = f1.isDirectory();
System.out.println("f1:" + dir1);//true
boolean dir2 = f2.isDirectory();
System.out.println("f2:" + dir2);//false
//String getName() 获取文件/文件名,包含后缀
String name = f2.getName();
System.out.println("文件名:"+name);
//long length() 获取文件大小,返回字节个数
long length = f2.length();
System.out.println("文件大小:" + length);
//long lastModified() 获取最后修改时间
long time = f2.lastModified();
System.out.println("最后修改时间:" + new Date(time));
//string getPath() 获取创建对象时的路径
String path = f2.getPath();
System.out.println("创建对象时的路径:" + path);
//String getAbsolutePath() 获取对象绝对路径
String absolutePath = f2.getAbsolutePath();
System.out.println("对象绝对路径:" + absolutePath);
}
}
运行结果:
f1:true
f3:false
f2:true
f4:false
f1:true
f2:false
文件名:1.txt
文件大小:6
最后修改时间:Thu Sep 05 11:01:21 CST 2024
创建对象时的路径:day08-code\test1\1.txt
对象绝对路径:D:\develop_tools\JAVA\itheima\code\advenceSE-code\day08-code\test1\1.txt
2.3 File创建和删除方法
File创建和删除方法 boolean mkdir() 创建单级文件夹,创建失败返回false boolean mkdirs() 创建多级文件夹 (常用) boolean createNewFile() 创建文件,文件存在返回false boolean delete() 删除文件或空文件夹,删除失败返回false (注意: 删除方法不走回收站,填用)
public class Demo3 {
public static void main(String[] args) throws IOException {
File f1 = new File("day08-code/test2");
File f2 = new File("day08-code/test2/test3");
File f3 = new File("day08-code/test2/2.txt");
//boolean mkdir() 创建单级文件夹,创建失败返回false
boolean mkdir = f2.mkdir();
System.out.println("mkdir:" + mkdir);//false
mkdir = f1.mkdir();
System.out.println("mkdir:" + mkdir);//true
//boolean mkdirs() 创建多级文件夹 (常用)
boolean mkdirs = f2.mkdirs();
System.out.println("mkdirs:" + mkdirs);//true
//boolean createNewFile() 创建文件,文件存在返回false
boolean newFile = f3.createNewFile();
System.out.println("newFile:" + newFile);//true
//boolean delete() 删除文件或空文件夹,删除失败返回false (注意: 删除方法不走回收站,填用)
boolean delete = f3.delete();
System.out.println("delete:" + delete);//true
boolean delete1 = f3.delete();
System.out.println("delete:" + delete1);//false
}
}
2.4 查看目录中的内容
查看目录中的内容 String[] list() 获取当前目录下所有的"一级文件名称"到一个字符串数组中去返回。 File[] listFiles() 获取当前目录下所有的"一级文件对象"到一个文件对象数组中去返回,包含隐藏文件(重点) 注意事项 当主调是文件,或者路径不存在时,返回null 当主调是空文件夹时,返回一个长度为0的数组 当主调是一个非空文件夹,但是没有权限访问该文件夹时,返回null
public class Demo4 {
public static void main(String[] args) {
//String[] list() 返回文件名数组
File parent = new File("D:\\develop_tools");
String[] list = parent.list();
for (String name : list) {
System.out.println(name);
}
System.out.println("--------------------------------");
//File[] listFiles() 返回文件数组
File[] files = parent.listFiles();
for (File file : files) {
System.out.println(file);
if(file.isFile()){
System.out.println("文件");
}else{
System.out.println("文件夹");
}
}
}
}
运行结果:
1.txt
Code
IDEA
JAVA
JDK
Typora
--------------------------------
D:\develop_tools\1.txt
文件
D:\develop_tools\Code
文件夹
D:\develop_tools\IDEA
文件夹
D:\develop_tools\JAVA
文件夹
D:\develop_tools\JDK
文件夹
D:\develop_tools\Typora
文件夹
2.5 案例练习:查找文件
需求: 从D:盘中,搜索“QQ.exe” 这个文件,找到后直接输出其位置。 分析: 先找出D:盘下的所有一级文件对象 遍历全部一级文件对象,判断是否是文件 如果是文件,判断是否是自己想要的 如果是文件夹,需要继续进入到该文件夹,重复上述过程
public class Demo5 {
public static void main(String[] args) {
findFile(new File("D:\\"), "QQ.exe");
}
/**
* 递归查找文件
* 参数1:目录对象
* 参数2:需要查找的文件
* 返回值void
*/
public static void findFile(File parent, String fileName) {
//1. 获取该目录下的所有文件
File[] files = parent.listFiles();
//2. 判断该文件/文件夹是否为空,如果当前文件/文件夹为空,直接返回
if(files == null || files.length == 0){
return;
}
//3. 遍历所有文件
for (File file : files) {
//4. 判断是否是文件
if (file.isFile()){
//4.1 判断文件名是否是目标文件
if(file.getName().equals(fileName)){
System.out.println("找到文件:" + file.getAbsolutePath());
}
}else {
//4.2 如果不是文件,进入到该文件夹,重复上述过程继续查找
findFile(file, fileName);
}
}
}
}
2.6 案例练习:删除非空文件夹
需求:删除非空文件夹
* 分析:
* ① File默认不可以删除非空文件夹
* ② 我们需要遍历文件夹,先删除里面的内容,再删除自己。
public class Test01 {
public static void main(String[] args) {
deleteFile(new File("D:\\aa-Test\\bb"));
deleteFile1(new File("D:\\aa-Test\\b"));
}
public static void deleteFile(File parent) {
// 判断文件是否存在,并且是否为文件夹
if (parent.exists() && parent.isDirectory()){
// 获取文件夹中的内容
File[] files = parent.listFiles();
// 判断文件夹是否为空
if(files != null ){
// 不空,遍历文件夹中的内容
for (File file : files) {
// 判断是否为文件
if(file.isFile()){
// 为文件,删除
file.delete();
}else{
// 为文件夹,递归,调用方法删除文件夹
deleteFile(file);
}
}
}
// 删除当前文件夹
parent.delete();
}
}
public static void deleteFile1(File parent) {
// 判断文件是否存在,并且是否为文件夹
if(parent.exists() && parent.isDirectory()){
// 获取文件夹中的内容
File[] files = parent.listFiles();
// 判断文件夹是否为空
if(files == null || files.length == 0){
// 为空,删除自己
parent.delete();
}else {
// 不为空,遍历文件夹中的内容
for (File file : files) {
// 判断是否为文件夹
if(file.isDirectory()){
// 递归
deleteFile1(file);
}else {
// 为文件,删除
file.delete();
}
}
// 判断文件夹是否为空
if(parent.listFiles().length==0){
// 为空,删除自己
parent.delete();
}
}
}
}
/**
* 检查文件夹是否存在:首先检查文件夹是否存在并且是一个目录。
* 检查文件夹是否为空:如果文件夹为空(files == null || files.length == 0),则尝试删除文件夹。
* 遍历文件夹内容:如果文件夹不为空,遍历文件夹中的所有文件和子文件夹。
* 递归删除子文件夹:对于每个子文件夹,递归调用 deleteFile1 方法进行删除。
* 删除文件:对于每个文件,直接调用 delete() 方法进行删除。
* 再次检查文件夹是否为空:在删除完所有内容后,再次调用 parent.listFiles() 检查文件夹是否为空,如果为空,则尝试删除文件夹。
*/
}
三、字符集
编码: 字符-->字节 byte[] getBytes() 使用平台的默认字符集将该String编码为一系列字节,将结果存储到新的字节数组中 byte[] getBytes(String charsetName) 使用指定的字符集将该String编码为一系列字节,将结果存储到新的字节数组中 解码: 字节-->字符 String(byte[] bytes) 通过使用平台的默认字符集解码指定的字节数组来构造新的String String(byte[] bytes, String charsetName) 通过指定的字符集解码指定的字节数组来构造新的String
public class Demo2 {
public static void main(String[] args) throws UnsupportedEncodingException {
//编码: 字符-->字节
String str = "我爱China";
byte[] bytes1 = str.getBytes();// 默认使用平台默认字符集
System.out.println(bytes1.length);
byte[] bytes2 = str.getBytes("GBK");
System.out.println(bytes2.length);
//解码: 字节-->字符
String s1 = new String(bytes1);// 默认使用平台默认字符集
System.out.println(s1);
String s2 = new String(bytes2, "GBK");
System.out.println(s2);
}
}
四、IO流(读写文件数据)
五、字节流
5.1 文件字节输入流
5.1.1 每次读取一个字节
作用: 读取文件中的内容到程序中,结果是字节 语法: FileInputStream(File file) 创建字节输入流管道与源文件接通 FileInputStream(String pathname) 创建字节输入流管道与源文件接通 方法(1次读1个字节) int read() 每次读取一个字节返回, 如果发现没有数据可读会返回-1
public class Demo1 {
public static void main(String[] args) throws IOException {
//1. 创建文件字节输入流(c_demo1.txt)
//方式一:
// File file = new File("day08-code/c_demo1.txt");
// FileInputStream fileInputStream = new FileInputStream(file);
//方式二:
FileInputStream fileInputStream = new FileInputStream("day08-code/c_demo1.txt");
//2. 读取文件中的内容
// int read = fileInputStream.read();
// char c = (char) read;
// System.out.println(c);
//2.1 定义一个文件读取的变量
int read;
//2.2 while中,读取一次,赋值到变量,判断是否!=-1
while ((read = fileInputStream.read()) != -1){
//2.3 读取到的字节转成char,并输出
System.out.print((char) read);
}
//3. 如果流操作完毕, 应该主动关闭流
fileInputStream.close();
}
}
1、文件字节输入流的作用是什么?
从磁盘中读取内容到程序中
2、每次读取一个字节的方法是哪个?
public int read()
3、每次读取一个字节存在什么问题?
读取性能较差,并且读取汉字输出会乱码。
5.1.2 每次读取多个字节
文件字节输入流(1次读多个字节)
int read(byte[] buffer) 每次用一个字节数组去读取数据, 返回字节数组读取了多少个字节,如果发现没有数据可读会返回-1.
public class Demo2 {
public static void main(String[] args) throws IOException {
//1. 创建文件字节输入流(c_demo2.txt)
FileInputStream fileInputStream = new FileInputStream("day08-code/c_demo2.txt");
//2. 读取文件中的内容
// //2.1 定义一个字节数组, 用来存储读取到的字节(数据传输)
// byte[] bytes = new byte[3];
// //2.2 调用方法read(byte[] buffer),将文件中的数据读到数组中
// int len = fileInputStream.read(bytes);
// //new String(bytes,字节数组的开始索引,长度): 将字节数组转成字符串
// System.out.println("读取了" + len + "个字节" + new String(bytes, 0, len));
//
// int len2 = fileInputStream.read(bytes);
// System.out.println("读取了" + len2 + "个字节" + new String(bytes,0,len2));
//
// int len3 = fileInputStream.read(bytes);
// System.out.println("读取了" + len3 + "个字节" + new String(bytes,0,len3));
//2.1 定义一个字节数组, 用来存储读取到的字节(数据传输)
byte[] bytes = new byte[3];
//2.2 使用while循环读取文件
//定义一个读取的长度,默认为空
int len;
//while循环,读取一次赋值到长度变量,判断是否!=-1,当返回-1的时候,表示文件读取完毕,退出循环
while ((len = fileInputStream.read(bytes)) != -1){
System.out.println("读取了" + len + "个字节" + new String(bytes,0,len));
}
//3. 如果流操作完毕, 应该主动关闭流
fileInputStream.close();
}
}
5.1.3 一次读取完全部字节
方式2: Java官方为InputStream提供了如下方法,可以直接把文件的全部字节读取到一个字节数组中返回。 public byte[] readAllBytes() 直接将当前字节输入流对应的文件对象的字节数据装到一个字节数组返回
public class Demo3 {
public static void main(String[] args) throws IOException {
//1. 创建文件字节输入流(c_demo3.txt)
File file = new File("day08-code/c_demo3.txt");
FileInputStream fileInputStream = new FileInputStream("day08-code/c_demo3.txt");
//2. 读取文件中的内容
//方式1: 定义一个跟文件同样大小的数组,一次接收所有
// byte[] bytes = new byte[(int) (file.length())];
// int read = fileInputStream.read(bytes);//返回读取的字节数
// String s = new String(bytes);
// System.out.println(s);
//方式2: 直接使用readAllBytes将文件中所有内容读取到数组
byte[] bytes1 = fileInputStream.readAllBytes();
System.out.println(new String(bytes1));
//3. 如果流操作完毕, 应该主动关闭流
fileInputStream.close();
}
}
5.2 文件字节输出流
作用: 向文件中写入字节内容 语法: FileOutputStream(String filepath) 创建字节输出流管道与源文件路径接通 例如: FileOutputStream fileOutputStream = new FileOutputStream("day08-code/c_demo4.txt");//不追加数据 fileOutputStream.write(97);//a fileOutputStream.write(98);//ab FileOutputStream(String filepath, boolean append) 创建字节输出流管道与源文件路径接通,可追加数据 例如: FileOutputStream fileOutputStream = new FileOutputStream("day08-code/c_demo4.txt",true);//追加数据 fileOutputStream.write(97);//a fileOutputStream.write(98);//aab(会追加一个a) 方法: void write(int a) 写一个字节出去 void write(byte[] buffer) 写一个字节数组出去 void write(byte[] buffer, int pos, int len) 写一个字节数组的一部分出去 void close() 关闭流 注意: 如果要写出换行, 需要写"\r\n"的字节数组表示形式
public class Demo4 {
public static void main(String[] args) throws IOException {
//创建文件字节输出流(c_demo4.txt)
FileOutputStream fileOutputStream = new FileOutputStream("day08-code/c_demo4.txt");
//写入数据
//写一个字节出去
fileOutputStream.write(97);
fileOutputStream.write(98);
//写一个字节数组出去
fileOutputStream.write("\r\n".getBytes());//换行
String str = "我da你";
fileOutputStream.write(str.getBytes());
fileOutputStream.write("\r\n".getBytes());//换行
//写一个字节数组的一部分出去
byte[] buffer = {97, 98, 99, 100,101,102};
fileOutputStream.write(buffer,1,3);//buffer数组,开始索引,长度
//关闭流
fileOutputStream.close();
}
}
5.3 文件复制
文件复制 源文件-->输入流-->程序-->输出流-->目标文件 步骤: 1. 创建文件的输入流,对应到源文件; 创建文件输出流,对应到目标文件 2. 使用输入流读取数据,使用输出流写出数据(边读边写) 3. 释放资源(关闭流)
public class Demo5 {
public static void main(String[] args) throws IOException {
//1. 创建文件的输入流,对应到源文件
FileInputStream fileInputStream = new FileInputStream("D:\\develop_tools\\JAVA\\itheima\\code\\advenceSE-code\\day08-code\\c_demo4.txt");
FileOutputStream fileOutputStream = new FileOutputStream("D:\\develop_tools\\JAVA\\itheima\\code\\advenceSE-code\\day08-code\\c_demo5.txt");
//2.读取文件中的数据
//定义一个长度
byte[] bytes = new byte[1024];
int len;
//while循环,读取一次,将读取长的复制到变量是,判断是否!=-1
while ((len = fileInputStream.read(bytes))!= -1){
//3.写入对应的文件
fileOutputStream.write(bytes,0,len);//每次读多长写多长
}
//4.关闭数据流(先开的后关)
fileOutputStream.close();
fileInputStream.close();
}
}