文章目录
第十一章 算法
一、排序算法
1.1 冒泡排序
1、定义:每次从数组中找出最大值放在数组的后面去
2、实现冒泡排序的关键步骤
(1)确定总共需要做几轮: 数组的长度-1.
(2)每轮比较几次
(3)当前位置大于后一个位置则交换数据
3、示例
public static void main(String[] args) {
int[] arr = {5, 2, 3, 1};
for (int i = 0; i < arr.length - 1; i++) {
// 定义一个循环控制每轮比较几次。
for (int j = 0; j < arr.length - i - 1; j++) {
// 判断当前位置的元素值,是否大于后一个位置处的元素值
if(arr[j] > arr[j+1]){
int temp = arr[j + 1];
arr[j + 1] = arr[j];
arr[j] = temp;
}
}
}
//返回数组的字符串表现形式
System.out.println(Arrays.toString(arr));
}
1.2 选择排序
1、定义:每轮选择当前位置,与后面的值比较,若后面的值小于该值,交换位置。
2、示例
public static void main(String[] args) {
int[] arr = {5, 1, 3, 2};
//控制选择几轮
for (int i = 0; i < arr.length - 1; i++) {
//控制每轮选择几次。
for (int j = i + 1; j < arr.length; j++) {
// 判断当前位置是否大于后面位置处的元素值,若大于则交换。
if(arr[i] > arr[j]){
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
}
}
System.out.println(Arrays.toString(arr));
}
二、查找算法
2.1 二分查找 (折半查找)
1、定义:数组中的数据必须是有序的。每次排除一半的数据,能够提高查询数据的性能。
2、关键步骤
(1)定义两个变量,分别记录开始索引(left)和结束索引(right)
(2)计算中间位置的索引,mid = (left+right)/2;
(3)每次查找中间mid位置的元素,和目标元素key进行比较。如果中间位置元素比目标元素小,left = mid+1。如果中间位置元素比目标元素大,right = mid-1。如果中间位置元素和目标元素相等,把mid返回。
3、示例
public class Test {
public static void main(String[] args) {
int[] arr = {7, 23, 79, 81, 103, 127, 131, 147};
System.out.println(binarySearch(arr, 150));
System.out.println(Arrays.binarySearch(arr, 81));
}
public static int binarySearch(int[] arr, int data){
// 定义两个变量,一个站在左边位置,一个站在右边位置
int left = 0;
int right = arr.length - 1;
// 定义一个循环控制折半。折半条件:left <= right
while (left <= right){
// 每次折半,都算出中间位置处的索引
int middle = (left + right) / 2;
// 判断当前要找的元素值,与中间位置处的元素值的大小情况。
if(data < arr[middle]){
// 往左边找,截止位置(右边位置) = 中间位置 - 1
right = middle - 1;
}else if(data > arr[middle]){
// 往右边找,起始位置(左边位置) = 中间位置 + 1
left = middle + 1;
}else {
// 中间位置处的元素值,正好等于我们要找的元素值
return middle;
}
}
return -1; // -1特殊结果,就代表没有找到数据
}
}
三、正则表达式
1、定义:就是由一些特定的字符组成,代表的是一个规则。
2、作用
(1)用来校验数据格式是否合法。
(2)在一段文本中查找满足要求的内容。
3、书写规则
4、应用
(1)正则表达式用于校验规则
//qq校验规则:qq不可为空,不是以0开头的,满足6-20之间的长度。
public static boolean checkQQ1(String qq){
//以数字1-9开头,//d是指后面的字符为数字0-9,还有5-19个数字
return qq != null && qq.matches("[1-9]\\d{5,19}");
}
//电话校验规则:校验用户输入的手机或座机,
public static boolean checkPhone(){
//手机号以1开头,第二位数字为3-9,\\d是指后面的字符为数字0-9,还有9个数字
//座机以0开头,\\d是指后面的字符为数字0-9,还有2-7个数字,接下来是“-”字符,?表示可有可无。
phone.matches("(1[3-9]\\d{9})|(0\\d{2,7}-?[1-9]\\d{4,19})")
}
(2)正则表达式用于查找信息
//从以下内容中爬取出,手机,邮箱,座机、400电话等信息。
public static void method1(){
String data = " 来黑马程序员学习Java,\n" +
" 电话:1866668888,18699997777\n" +
" 或者联系邮箱:boniu@itcast.cn,\n" +
" 座机电话:01036517895,010-98951256\n" +
" 邮箱:bozai@itcast.cn,\n" +
" 邮箱:dlei0009@163.com,\n" +
" 热线电话:400-618-9090 ,400-618-4000,4006184000,4006189090";
// 1、定义爬取规则
String regex = "(1[3-9]\\d{9})|(0\\d{2,7}-?[1-9]\\d{4,19})|(\\w{2,}@\\w{2,20}
(\\.\\w{2,10}){1,2})" + "|(400-?\\d{3,7}-?\\d{3,7})";
// 2、把正则表达式封装成一个Pattern对象
Pattern pattern = Pattern.compile(regex);
// 3、通过pattern对象去获取查找内容的匹配器对象。
Matcher matcher = pattern.matcher(data);
// 4、定义一个循环开始爬取信息
while (matcher.find()){
String rs = matcher.group(); // 获取到了找到的内容了。
System.out.println(rs);
}
}
(3)正则表达式用于搜索替换和分割内容
public class Test {
public static void main(String[] args) {
// 1、public String replaceAll(String regex , String newStr):搜索替换
// 需求1:请把下面字符串中的不是汉字的部分替换为 “-”
String s1 = "古力娜扎ai8888迪丽热巴999aa5566马尔扎哈fbbfsfs42425卡尔扎巴";
System.out.println(s1.replaceAll("\\w+", "-"));
// 需求2:“我我我喜欢编编编编编编编编编编编编程程程”,需要优化成“我喜欢编程”。
String s2 = "我我我喜欢编编编编编编编编编编编编程程程";
//(.)是一组.匹配任意字符,\\1是分组引用,+是重复的字
//$1代表组内重复的字
System.out.println(s2.replaceAll("(.)\\1+", "$1"));
// 2、public String[] split(String regex):分割字符串,返回一个字符串数组。
// 需求1:请把下面字符串中的人名取出来,使用切割来做
String s3 = "古力娜扎ai8888迪丽热巴999aa5566马尔扎哈fbbfsfs42425卡尔扎巴";
String[] names = s3.split("\\w+");
System.out.println(Arrays.toString(names)); //[古力娜扎,迪丽热巴,马尔扎哈,卡尔扎巴]
}
}
四、方法递归
1、定义:方法调用自身的形式称为方法递归 (recursion)。
2、形式
(1)直接递归:方法自己调用自己。
(2)间接递归:方法调用其他方法,其他方法又回调方法自己。
3、递归算法三要素:①递归的公式;②递归的终结点;③递归的方向必须走向终结点。
4、示例
第十二章 file、IO流和特殊文件
一、file
1、定义:File是java.io.包下的类,File类的对象,用于代表当前操作系统的文件 (可以是文件、或文件夹)。
2、常用方法
(1)创建对象
public static void main(String[] args) {
// 1、创建一个File对象,指代某个具体的文件ab.txt。
// File f1 = new File("D:/resource/ab.txt");
// File f1 = new File("D:\\resource\\ab.txt");
// 路径分隔符resource
File f1 = new File("D:" + File.separator +"resource" + File.separator + "ab.txt");
System.out.println(f1.length()); // 文件大小
//File对象既可以代表文件、也可以代表文件夹
File f2 = new File("D:/resource");
System.out.println(f2.length());
// File对象还可以指代一个不存在的文件路径
File f3 = new File("D:/resource/aaaa.txt"); //绝对路径
System.out.println(f3.length()); //0
System.out.println(f3.exists()); // false
// 相对路径,默认是直接去工程file-io-app下寻找文件的。
File f4 = new File("file-io-app\\src\\itheima.txt");
System.out.println(f4.length());
}
(2)判断文件类型、获取文件信息功能
(3)创建文件、删除文件
public static void main(String[] args) throws Exception {
// public boolean createNewFile():创建一个新文件(文件内容为空),返回布尔值。
File f1 = new File("D:/resource/itheima2.txt");
System.out.println(f1.createNewFile());
// public boolean mkdir():用于创建文件夹,注意:只能创建一级文件夹
File f2 = new File("D:/resource/aaa");
System.out.println(f2.mkdir());
//public boolean mkdirs():用于创建文件夹,注意:可以创建多级文件夹
File f3 = new File("D:/resource/bbb/ccc/ddd/eee/fff/ggg");
System.out.println(f3.mkdirs());
// public boolean delete():删除文件,或者空文件,注意:不能删除非空文件夹。
System.out.println(f1.delete());
}
(4)遍历文件夹
使用listFiles方法时的注意事项
① 当主调是文件,或者路径不存在时,返回null
② 当主调是空文件夹时,返回一个长度为0的数组
③ 当主调是一个有内容的文件夹时,将所有一级文件和文件夹的路径放在File数组中返回。
④ 当主调是一个文件夹,且里面有隐藏文件时,将里面所有文件和文件夹的路径放在File数组中返回,包含隐藏文件当主调是一个文件夹,但是没有权限访问该文件夹时,返回null。
public static void main(String[] args) {
// public String[] list():获取当前目录下所有的"一级文件名称"到一个字符串数组中去返回。
File f1 = new File("D:\\course\\待研发内容");
String[] names = f1.list();
for (String name : names) {
System.out.println(name);
}
// public File[] listFiles():获取当前目录下所有"一级文件对象"到一个文件对象数组中去返回
File[] files = f1.listFiles();
for (File file : files) {
System.out.println(file.getAbsolutePath());
}
}
3、示例-在D:\\
判断下搜索QQ.exe这个文件,然后直接输出。
public class RecursionTest3 {
public static void main(String[] args) throws Exception {
searchFile(new File("D:/") , "QQ.exe");
}
//dir:目录 fileName:要搜索的文件名称
public static void searchFile(File dir, String fileName) throws Exception {
// 1、把非法的情况都拦截住
if(dir == null || !dir.exists() || dir.isFile()){
return; // 代表无法搜索
}
// 2、dir不是null,存在,一定是目录对象。
// 获取当前目录下的全部一级文件对象。
File[] files = dir.listFiles();
// 3、判断当前目录下是否存在一级文件对象,以及是否可以拿到一级文件对象。
if(files != null && files.length > 0){
// 4、遍历全部一级文件对象。
for (File f : files) {
// 5、判断文件是否是文件,还是文件夹
if(f.isFile()){
// 是文件,判断这个文件名是否是我们要找的
if(f.getName().contains(fileName)){
System.out.println("找到了:" + f.getAbsolutePath());
Runtime runtime = Runtime.getRuntime();
runtime.exec(f.getAbsolutePath());
}
}else {
// 是文件夹,继续重复这个过程(递归)
searchFile(f, fileName);
}
}
}
}
}
二、IO流
2.1 定义:IO流又称输入输出流,用于读写数据的(可以读写文件,或网络中的数据…)。
2.2 IO流的分类和体系结构
1、按流中数据的最小单位,IO流分为四大类:
(1)字节输入流:以内存为基准,来自磁盘文件/网络中的数据以字节的形式读入到内存中去的流。
(2)字节输出流:以内存为基准,把内存中的数据以字节写出到磁盘文件或者网络中去的流。
(3)字符输入流:以内存为基准,来自磁盘文件/网络中的数据以字符的形式读入到内存中去的流。
(4)字符输出流: 以内存为基准,把内存中的数据以字符写出到磁盘文件或者网络介质中去的流。
2、IO流的体系
2.3 IO流-字节流
1、FileInputStream(文件字节输入流)
(1)作用:以内存为基准,可以把磁盘文件中的数据以字节的形式读入到内存中去。
(2)常用方法
(3)示例
public static void main(String[] args) throws Exception {
//1、创建文件字节输入流管道,与源文件接通。
//InputStream is=new FileInputStream(new File("file-io-app\\src\\itheima.txt"));
//简化写法,参数为相对路径
InputStream is = new FileInputStream(("file-io-app\\src\\itheima.txt"));
//2、读取文件的字节数据。
// public int read():每次读取一个字节返回
int b1 = is.read();
System.out.print((char) b1);
//循环改造
int b; // 用于记住读取的字节。
while ((b = is.read()) != -1){
System.out.print((char) b);
}
// public int read(byte[] buffer):每次读取多个字节返回int
byte[] buffer1 = new byte[3];
int len1 = is.read(buffer1);
String rs1 = new String(buffer1);
System.out.print(rs1); //abc
//循环改造
byte[] buffer = new byte[3];
int len; // 记住每次读取了多少个字节。 abc 66
while ((len = is.read(buffer)) != -1){
// 转成字符串形式,从0开始到len,读取多少,倒出多少。
String rs = new String(buffer, 0 , len);
System.out.print(rs); //abccc
}
//3、流使用完毕之后,必须关闭!释放系统资源!
is.close();
}
(4)用文件字节输入流解决读取汉字输出乱码
① 定义一个字节数组与被读取的文件大小一样大,然后使用该字节数组,一次读完文件的全部字节。
② Java官方为InputStream提供了如下方法,可以直接把文件的全部字节读取到一个字节数组中返回
2、FileOutputStream(文件字节输出流)
(1)作用:以内存为基准,把内存中的数据以字节的形式写出到文件中去。
(2)常用方法
(3)示例
public static void main(String[] args) throws Exception {
// 1、创建一个字节输出流管道与目标文件接通。
// 覆盖管道:覆盖之前的数据
//OutputStream os =new FileOutputStream("file-io-app/src/itheima04out.txt");
// 追加数据的管道
OutputStream os=new FileOutputStream("file-io-app/src/itheima04out.txt", true);
// 2、输出字节数据出去
os.write(97); // 97就是一个字节,代表a
os.write('b'); // 'b'也是一个字节
// os.write('磊'); // 中文为三个字节[ooo],可以运行但是会乱码
byte[] bytes = "我爱你中国abc".getBytes(); //转换为byte数组
os.write(bytes); //我爱你中国abc
os.write(bytes, 0, 15); //我爱你中国
os.write("\r\n".getBytes()); // 换行符
os.close(); // 关闭流
}
3、文件复制——复制一张图片,从磁盘D:/resource/meinv.png的一个位置,复制到C:/data/meinv.png位置。
public static void main(String[] args) throws Exception {
// 1、创建一个字节输入流管道与源文件接通
InputStream is = new FileInputStream("D:/resource/meinv.png");
// 2、创建一个字节输出流管道与目标文件接通。
OutputStream os = new FileOutputStream("C:/data/meinv.png");
// 3、创建一个字节数组,负责转移字节数据。
byte[] buffer = new byte[1024]; // 1KB.
// 4、从字节输入流中读取字节数据,写出去到字节输出流中。读多少写出去多少。
int len; // 记住每次读取了多少个字节。
while ((len = is.read(buffer)) != -1){
os.write(buffer, 0, len);
}
os.close();
is.close();
System.out.println("复制完成!!");
}
4、释放资源
(1)try-catch-finally
① 格式
try{
}catch(IOException e){
e.printStackTrace();
}finally{
}
② finaly代码区的特点:无论try中的程序是正常执行了,还是出现了异常,最后都一定会执行finally区,除非JVM终止。
③ 作用:一般用于在程序执行完成后进行资源的释放操作 (专业级做法)。
(2)try-with-resource
① 格式
try(定义资源1;定义资源2){
可能出现异常的代码;
}catch(异常类名 变量名){
异常的处理代码;
}
2.4 IO流-字符流
1、FileReader(文件字符输入流)
(1)作用:以内存为基准,可以把文件中的数据以字符的形式读入到内存中去。
(2)常用方法
(3)示例
public static void main(String[] args) {
//自动释放资源
try (
// 创建一个文件字符输入流管道与源文件接通
Reader fr = new FileReader("io-app2\\src\\itheima01.txt");
){
/* read() 每次读取一个字符,性能较差
int c; // 记住每次读取的字符编号。
while ((c = fr.read()) != -1){
System.out.print((char) c);
}
*/
// read(char[] buffer) 每次读取多个字符,性能较好
char[] buffer = new char[3];
int len; // 记住每次读取了多少个字符。
while ((len = fr.read(buffer)) != -1){
// 读取多少倒出多少
System.out.print(new String(buffer, 0, len));
}
} catch (Exception e) {
e.printStackTrace();
}
}
2、FileWriter(文件字符输出流)
(1)作用:以内存为基准,把内存中的数据以字符的形式写出到文件中去。
(2)常用方法
(3)注意事项:字符输出流写出数据后,必须刷新流,或者关闭流,写出去的数据才能生效。
fw.flush(); //刷新流
fw.close(); //关闭流
(4)示例
public static void main(String[] args) {
try (
//1、创建一个文件字符输出流管道与目标文件接通,追加数据
Writer fw = new FileWriter("io-app2/src/itheima02out.txt", true);
){
// 1、public void write(int c):写一个字符
fw.write('a'); //a
fw.write(97); //a
fw.write('磊'); // 磊
// 2、public void write(String c)写一个字符串
fw.write("我爱你中国abc");
fw.write("\r\n"); // 换行
// 3、public void write(String c ,int pos ,int len):写字符串的一部分出去
fw.write("我爱你中国abc", 0, 5); //我爱你中国
// 4、public void write(char[] buffer):写一个字符数组出去
char[] buffer = {'黑', '马', 'a', 'b', 'c'};
fw.write(buffer); //黑马abc
// 5、public void write(char[] buffer ,int pos ,int len):写字符数组的一部分出去
fw.write(buffer, 0, 2);
} catch (Exception e) {
e.printStackTrace();
}
}
2.4 IO流-缓冲流
1、BufferedInputStream(字节缓冲输入流)和BufferedOutputStream(字节缓冲输出流)
(1)作用:提高字节流读写数据的性能。字节缓冲输入流自带了8KB缓冲池;字节缓冲输出流也自带了8KB缓冲池。
(2)常用方法
(3)示例
public static void main(String[] args) {
try (
InputStream is = new FileInputStream("io-app2/src/itheima01.txt");
// 1、定义一个字节缓冲输入流包装原始的字节输入流
InputStream bis = new BufferedInputStream(is);
OutputStream os = new FileOutputStream("io-app2/src/itheima01_bak.txt");
// 2、定义一个字节缓冲输出流包装原始的字节输出流
OutputStream bos = new BufferedOutputStream(os);
){
byte[] buffer = new byte[1024];
int len;
while ((len = bis.read(buffer)) != -1){
bos.write(buffer, 0, len);
}
System.out.println("复制完成!!");
} catch (Exception e) {
e.printStackTrace();
}
}
2、BufferedReader(字符缓冲输入流)
(1)作用:自带8K (8192)的字符缓冲池,可以提高字符输入流读取字符数据的性能
(2)常用方法
(3)示例
public static void main(String[] args) {
try (
Reader fr = new FileReader("io-app2\\src\\itheima04.txt");
//创建字符缓冲输入流包装原始的字符输入流,不能用多态,否则不能调用BufferedReader特有方法
BufferedReader br = new BufferedReader(fr);
){
String line; // 记住每次读取的一行数据
while ((line = br.readLine()) != null){
System.out.println(line);
}
} catch (Exception e) {
e.printStackTrace();
}
}
2、BufferedWriter(字符缓冲输出流)
(1)作用:自带8K (8192)的字符缓冲池,可以提高字符输出流读取字符数据的性能
(2)常用方法
2.5 IO流-转换流
1、不同编码读取出现乱码的问题
(1)若代码编码和被读取的文本文件的编码是一致的,使用字符流读取文本文件时不会出现乱码。
(2)若代码编码和被读取的文本文件的编码是不一致的,使用字符流读取文本文件时会出现乱码。
2、InputStreamReader(字符输入转换流)
(1)作用:解决不同编码时,字符流读取文本内容乱码的问题。
(2)解决思路:先获取文件的原始字节流,再将其按真实的字符集编码转成字符输入流,这样字符输入流中的字符就不乱码了。
(3)常用方法
3、OutputStreamWriter(字符输出转换流)
(1)作用:可以控制写出去的字符使用什么字符集编码
(2)解决思路:获取字节输出流,再按照指定的字符集编码将其转换成字符输出流,以后写出去的字符就会用该字符集编码了。
(3)常用方法
2.6 IO流-打印流
1、PrintStream和PrintWriter(打印流)
2、作用: 打印流可以实现更方便、更高效的打印数据出去,能实现打印啥出去就是啥出去。
3、常用方法
① PrintStream
② PrintWriter
4、输出语句的重定向
(1)作用:可以把输出语句的打印位置改到某个文件中去。
(2)示例
public class PrintTest2 {
public static void main(String[] args) {
System.out.println("老骥伏枥");
System.out.println("志在千里");
try ( PrintStream ps = new PrintStream("io-app2/src/itheima09.txt"); ){
// 把系统默认的打印流对象改成自己设置的打印流
System.setOut(ps);
System.out.println("烈士暮年");
System.out.println("壮心不已");
} catch (Exception e) {
e.printStackTrace();
}
}
}
2.7 IO流-数据流
1、DataOutputStream(数据输出流)
(1)作用:允许把数据和其类型一并写出去。
(2)常用方法
(3)示例
public static void main(String[] args) {
try (
DataOutputStream dos =new DataOutputStream(new FileOutputStream("io-app2/src/itheima10out.txt"));
){
dos.writeInt(97);
dos.writeDouble(99.5);
dos.writeBoolean(true);
dos.writeUTF("黑马程序员666!");
} catch (Exception e) {
e.printStackTrace();
}
}
2、DataInputStream(数据输入流)
(1)作用:用于读取特定类型的数据。
(2)常用方法
(3)示例
public static void main(String[] args) {
try (
DataInputStream dis = new DataInputStream(new FileInputStream("io-app2/src/itheima10out.txt"));
){
int i = dis.readInt();
System.out.println(i); //97
double d = dis.readDouble();
System.out.println(d); //99.5
boolean b = dis.readBoolean();
System.out.println(b); //true
String rs = dis.readUTF();
System.out.println(rs); //黑马程序员666!
} catch (Exception e) {
e.printStackTrace();
}
}
2.8 IO流-序列化流
1、ObjectOutputStraem(对象字节输出流)
(1)作用:可以把Java对象进行序列化: 把Java对象存入到文件中去。
(2)常用方法
(3)注意事项:对象如果要参与序列化,必须实现序列化接口 (java.io.Serializable)。
(4)示例
//对象如果要参与序列化,必须实现序列化接口 (java.io.Serializable)
public class User implements Serializable {
private String loginName;
private String userName;
private int age;
// transient 这个成员变量将不参与序列化。
private transient String passWord;
public User() {
}
public User(String loginName, String userName, int age, String passWord) {
this.loginName = loginName;
this.userName = userName;
this.age = age;
this.passWord = passWord;
}
//调用tostring,打印内容
@Override
public String toString() {
return "User{" +"loginName='" + loginName + '\'' + ", userName='" + userName + '\'' +
", age=" + age +", passWord='" + passWord + '\'' +'}';
}
}
public class Test1ObjectOutputStream {
public static void main(String[] args) {
try (
//创建一个对象字节输出流包装原始的字节输出流。
ObjectOutputStream oos =new ObjectOutputStream(new FileOutputStream("io-app2/src/itheima11out.txt"));
){
// 1、创建一个Java对象。
User u = new User("admin", "张三", 32, "666888xyz");
// 3、序列化对象到文件中去
oos.writeObject(u);
System.out.println("序列化对象成功!!");
} catch (Exception e) {
e.printStackTrace();
}
}
}
2、ObjectInputStream(对象字节输入流)
(1)作用:可以把Java对象进行反序列化: 把存储在文件中的Java对象读入到内存中来。
(2)常用方法
(3)示例
public class Test2ObjectInputStream {
public static void main(String[] args) {
try (
// 1、创建一个对象字节输入流管道,包装 低级的字节输入流与源文件接通
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("io-app2/src/itheima11out.txt"));
){
User u = (User) ois.readObject();
System.out.println(u);
//User{loginName='admin',userName='张三',age=32,passWord='null'}
} catch (Exception e) {
e.printStackTrace();
}
}
}
(4)注意事项:如果要一次序列化多个对象,用一个ArrayList集合存储多个对象,然后直接对集合进行序列化( ArrayList集合已经实现了序列化接口)。
2.9 IO框架
1、框架
(1)定义:解决某类问题,编写的一套类、接口等,可以理解成一个半成品,大多框架都是第三方研发的。在框架的基础上开发,可以得到优秀的软件架构,并能提高开发效率。
(2)形式:一般是把类、接口等编译成class形式,再压缩成一个jar结尾的文件发行出去。
2、IO框架
(1)定义:封装了lava提供的对文件、数据进行操作的代码,对外提供了更简单的方式来对文件进行操作,对数据进行读写等。
(2)Commons-io是apache开源基金组织提供的一组有关IO操作的小框架,目的是提高IO流的开发效率。
(3)导入commons-io-2.11.0.jar到项目中的步骤
① 在项目中创建一个文件夹: lib
② 将commons-io-2.6.jar文件复制到lib文件夹
③ 在jar文件上点右键,选择 Add as Library -> 点击OK
④ 在类中导包使用
(4)示例
public static void main(String[] args) throws Exception {
//1.复制文件
FileUtils.copyFile(new File("io-app2\\src\\itheima01.txt"), new File("io-app2/src/a.txt"));
//2.复制文件夹
FileUtils.copyDirectory(new File("D:\\resource\\私人珍藏"), new File("D:\\resource\\私人珍藏3"));
//3.删除文件夹
FileUtils.deleteDirectory(new File("D:\\resource\\私人珍藏3"));
// Java提供的原生的一行代码搞定很多事情
Files.copy(Path.of("io-app2\\src\\itheima01.txt"), Path.of("io-app2\\src\\b.txt"));
System.out.println(Files.readString(Path.of("io-app2\\src\\itheima01.txt")));
}
}
三、特殊文件
3.1 properties文件
1、定义:properties文件,称为属性文件,它可以很方便的存储一些类似于键值对的数据。经常当做软件的配置文件使用。
2、Properties是一个Map集合(键值对集合),但是我们一般不会当集合使用。Properties是用来代表属性文件的,通过Properties可以读写属性文件里的内容。
3、常用方法
① 使用Properties读取属性文件里的键值对数据
public class PropertiesTest1 {
public static void main(String[] args) throws Exception {
// 1、创建一个Properties的对象出来(键值对集合,空容器)
Properties properties = new Properties();
// 2、开始加载属性文件中的键值对数据到properties对象中去
properties.load(new FileReader("properties-xml-log-app\\src\\users.properties"));
System.out.println(properties);
// 3、根据键取值
System.out.println(properties.getProperty("赵敏"));
System.out.println(properties.getProperty("张无忌"));
// 4、遍历全部的键和值。
Set<String> keys = properties.stringPropertyNames();
for (String key : keys) {
//再根据键获取值
String value = properties.getProperty(key);
System.out.println(key + "---->" + value);
}
properties.forEach((k, v) -> {
System.out.println(k + "---->" + v);
});
}
}
② 使用Properties把键值对数据写出到属性文件里去
public class PropertiesTest2 {
public static void main(String[] args) throws Exception {
// 1、创建Properties对象出来,先用它存储一些键值对数据
Properties properties = new Properties();
properties.setProperty("张无忌", "minmin");
properties.setProperty("殷素素", "cuishan");
properties.setProperty("张翠山", "susu");
// 2、把properties对象中的键值对数据存入到属性文件中去
properties.store(new FileWriter("properties-xml-log-app/src/users2.properties")
, "i saved many users!");
}
}
3.2 XML文件
1、定义:XML文件,本质是一种数据的格式,可以用来存储复杂的数据结构和数据关系。
2、语法规则
(1)XML中的 <标签名> 称为一个标签或一个元素,一般是成对出现的。XML中的标签名可以自己定义 (可扩展),但必须要正确的嵌套。XML中的标签可以有属性。
(2)XML中只能有一个根标签;文档声明必须是第一行。
(3)文件中放置的是XML格式的数据,这个文件就是XML文件,后缀一般要写成.xml。
(4)如果标签文本中有这些特殊字符,需要用一些占位符代替。
< 表示 <
> 表示 >
& 表示 &
' 表示 '
" 表示 "
(5)XML中可以写一个叫CDATA的数据区: <![CDATA[..内容... ]]>,里面的内容可以随便写。
3、应用场景:经常用来做为系统的配置文件,或者作为一种特殊的数据结构,在网络中进行传输。
4、解析XML文件——Dom4j框架
(1)思想:文本对象模型
(2)常用方法
① 解析XML文件——得到Document对象
② Document
③ Element提供的方法
(3)示例
public static void main(String[] args) throws Exception {
// 1、创建一个Dom4J框架提供的解析器对象
SAXReader saxReader = new SAXReader();
// 2、使用saxReader对象把需要解析的XML文件读成一个Document对象。
Document document = saxReader.read("properties-xml-log-app\\src\\helloworld.xml");
// 3、从文档对象中解析XML文件的全部数据了
Element root = document.getRootElement();
System.out.println(root.getName());
// 4、获取根元素下的全部一级子元素。
List<Element> elements = root.elements("user");
for (Element element : elements) {
System.out.println(element.getName());
}
// 5、获取当前元素下的某个子元素。
Element people = root.element("people");
System.out.println(people.getText());
// 如果下面有很多子元素user,默认获取第一个。
Element user = root.element("user");
// 6、获取元素的属性信息呢?
Attribute id = user.attribute("id");
System.out.println(id.getName());
System.out.println(id.getValue());
List<Attribute> attributes = user.attributes();
// 7、如何获取全部的文本内容:获取当前元素下的子元素文本值
System.out.println(user.elementText("name"));
Element data = user.element("data");
System.out.println(data.getText());
System.out.println(data.getTextTrim()); // 取出文本去除前后空格
}
5、XML约束
(1)定义:就是限制XML文件只能按照某种格式进行书写。
(2)约束文档:专门用来限制xml书写格式的文档,比如: 限制标签、属性应该怎么写。
(3)约束文档的分类:DTD文档和Schema文档
3.3 日志
1、定义:可以将系统执行的信息,方便的记录到指定的位置(控制台、文件中、数据库中)。可以随时以开关的形式控制日志的启停,无需侵入到源代码中去进行修改。
2、日志框架——logback
(1)步骤
① 导入logback框架(slftj-api.jar、logback-core.jar、logback-classes.jar)到项目中去。
② 将logback.xml配置文件复制粘贴到src目录下(必须是src目录)。
③ 创建Logback框架提供的Logger对象,然后用Logger对象调用其提供的方法就可以记录系统的日志信息。
(2)示例
public class LogBackTest {
// 创建一个Logger日志对象
public static final Logger LOGGER = LoggerFactory.getLogger("LogBackTest");
public static void main(String[] args) {
//while (true) {
try {
LOGGER.info("chu法方法开始执行~~~");
chu(10, 0);
LOGGER.info("chu法方法执行成功~~~");
} catch (Exception e) {
LOGGER.error("chu法方法执行失败了,出现了bug~~~");
}
}
public static void chu(int a, int b){
LOGGER.debug("参数a:" + a);
LOGGER.debug("参数b:" + b);
int c = a / b;
LOGGER.info("结果是:" + c);
}
}