文章目录
异常
认识异常
异常就是程序出现的问题
自定义异常
java不能为所有的异常提供类,所以有需要自己定义就行
自定义运行异常
package Rxception;
public class Demo1 {
public static void main(String[] args) {
try {
saveAge(1010);
}catch (Exception e){
e.printStackTrace();
}
}
//保存一个合理的年龄
public static void saveAge(int age){
if (age>0&&age<150){
System.out.println("年龄被保存:"+age);
}else {
//用一个异常对象封装这个问题
//throw是抛出异常
throw new AgeIllegalRuntimeException("age is illegal,your age is " + age);
}
}
}
class AgeIllegalRuntimeException extends RuntimeException{
public AgeIllegalRuntimeException() {
}
//message:异常出现的原因
public AgeIllegalRuntimeException(String message) {
super(message);
}
}
自定义编译时异常
public class Demo1 {
public static void main(String[] args) {
try {
saveAge(1010);
}catch (AgeIllegalRuntimeException e){
e.printStackTrace();
}
// saveAge(1000);//写的时候就会报错
}
//保存一个合理的年龄
public static void saveAge(int age) throws AgeIllegalRuntimeException{
if (age>0&&age<150){
System.out.println("年龄被保存:"+age);
}else {
//用一个异常对象封装这个问题
//throw 抛出这个异常
//throws 用在方法上 抛出方法内部的异常
throw new AgeIllegalRuntimeException("age is illegal,your age is " + age);
}
}
}
class AgeIllegalRuntimeException extends Exception{
public AgeIllegalRuntimeException() {
}
//message:异常出现的原因
public AgeIllegalRuntimeException(String message) {
super(message);
}
}
异常处理
开发中常见的异常处理
捕获异常,记录异常,相应合适的信息给用户
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class Demo2 {
public static void main(String[] args) {
try {
timeToFormat("2024-1 12:12:11");
} catch (Exception e) {
e.printStackTrace();//异常信息
System.out.println("异常");
}
}
public static void timeToFormat(String time) throws Exception {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Date date =sdf.parse(time);
System.out.println(date);
}
}
捕获异常,尝试修复
import java.util.Scanner;
public class Demo3 {
public static void main(String[] args) {
while (true) {
try {
getMoney();
break;
} catch (Exception e) {
System.out.println("请输入合理的数字");
// throw new RuntimeException(e);
}
}
}
public static void getMoney(){
Scanner sc =new Scanner(System.in);
while (true) {
System.out.print("请输入合适的价格:");
double money = sc.nextDouble();
if (money>=0){
System.out.println(money);
break;
}else {
System.out.println("价格不合理");
}
}
}
}
API:集合
前面学过一个ArrayList
集合,这里单独领出来就是进阶,常见的都是(集合非常重要)
Collection:单列集合
List
:特点->添加的元素是有序的(存和取的顺序一样)、可重复、有索引ArrayList
LinkList
Set
:特点->添加的元素是无序的、不重复、无索引HashSet
:无序、不重复、无索引LinkedHashSet
:有序、不重复、无索引
TreeSet
:默认升序排序、不重复、无索引
泛型的都是
Collection常用的方法
Collection的方法是单列集合所有通用的
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
public class Demo {
public static void main(String[] args) {
Collection<String>c = new ArrayList<>();//实现类给接口
//添加数据 public boolean add(E e);
c.add("111");
c.add("java");
System.out.println(c);
//清空集合 public void clear();
c.clear();
System.out.println(c);
//集合是否为空 public boolean isEmpty();
System.out.println(c.isEmpty());
//集合大小 public boolean size();
System.out.println(c.size());
//判断集合是否包含某个元素 public boolean contains(Object obj);
c.add("java1");
c.add("java2");
c.add("java3");
System.out.println(c.contains("java1"));
//删除集合中的元素 默认删除前面的一个 public boolean remove(E e);
c.remove("java3");
System.out.println(c);
//把集合转化为数组 public Object[] toArray();
Object[] arr1 = c.toArray();
System.out.println(Arrays.toString(arr1));
String[]arr2=c.toArray(new String[c.size()]);
System.out.println(Arrays.toString(arr2));
//把一个集合的元素追加到另外一个集合中 如下 c0是不会被改变的 c追加c0的数据
Collection<String> c0 = new ArrayList<>();
c0.add("java3");
c0.add("java4");
c.addAll(c0);
System.out.println(c);
System.out.println(c0);
}
}
Collection常用的遍历方式
Collection的遍历方式是单列集合所有通用的
- 迭代器遍历
- 增强for
- lambda表达式
迭代器
数组没有迭代器Iterator
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.function.Consumer;
public class BianLi {
public static void main(String[] args) {
Collection<String> c = new ArrayList<>();
c.add("yb0os1");
c.add("java");
c.add("go");
c.add("matlab");
c.add("python");
c.add("c/c++");
//1、迭代器遍历
//迭代器取到的是第一个元素
//iter.next() 是取出当前的元素 然后迭代器后移
//hasNext() 判断当前迭代器存不存在元素
for (Iterator<String> iter = c.iterator(); iter.hasNext(); ) {
System.out.println(iter.next());
}
System.out.println("----------");
//2、增强for 本质就是迭代器遍历简化写法
// 也可以遍历数组
for (String s : c) {
System.out.println(s);
}
System.out.println("----------");
//3、Lambda表达式
//default void forEach(Consumer<? super T>action);
/*c.forEach(new Consumer<String>() {
@Override
public void accept(String s) {
System.out.println(s);
}
});*/
// c.forEach(s ->System.out.println(s));
c.forEach(System.out::println);
}
}
List集合
list集合特有的方法
import java.util.ArrayList;
import java.util.List;
public class _List_ {
public static void main(String[] args) {
/**
* 1、for循环遍历
* 2、迭代器遍历
* 3、增强for遍历
* 4、lambda表达式遍历
*/
List<String>list = new ArrayList<>();
list.add("至尊宝");
list.add("牛魔王");
list.add("紫霞仙子");
list.add("红孩儿");
for (int i = 0; i < list.size(); i++) {
System.out.println(list.get(i));
}
}
}
ArrayList
和LinkedList
底层数据结构不同
ArrayList
底层结构
ArrayList
基于数组实现,根据索引查询速度快、删除效率低、插入数据效率低
底层原理
- 无参构造器构造集合的时候,底层创建一个长度为0的数组
- 当第一次插入数据的时候,底层会创建一个长度为10的数组代替原先的数组
- 数组存满时,扩容1.5倍
- 当一次性加入多个元素时,如果扩容1.5倍后依旧存不下,那么新创建的数组以实际长度为准(旧size+插入元素的size)
应用场景
- 适合:根据索引查数据
- 不适合:数据量很大,又需要频繁的增删操作
LinkedList
底层结构
LinkedList
基于双链表实现,根据索引查询速度慢、删除效率高、插入数据效率高
应用场景
- 设计队列
- 设计栈,可以直接用push、pop(LinkedList使用)
Vector
底层结构 (线程安全)
arraylist是线程不安全的
vector的方法一般都是带着synchronized
Set集合
set集合几乎没有独有的方法
哈希值:int类型,每个对象都有自己的哈希值 hashCode
- 同一个对象多次调用hashCode方法返回的哈希值是相同的
- 不同的对象一般哈希值是不同的(哈希碰撞)
HashSet
无序、不重复、无索引
基于哈希表
- JDK8之前 哈希表=数组+链表
- JDK8之后 哈希表=数组+链表+红黑树
底层原理
JDK8之前HashSet
-
首次添加数据的时候,默认创建一个长度为16的数组,默认加载因子为0.75,数组名为table
-
使用元素的哈希值对数组长度进行求余,计算应该存入的位置
- 求余结果的位置是null,直接存入
- 求余结果的位置不是null,那么依次调用equals()方法比较,相等不存,不相等要存
- JDK8之前新元素存入数组,老元素挂在新元素下面
- JDK8之后新元素直接挂在老元素下面
-
当占有16*0.75=12的时候,扩容2倍
JDK8开始之后,当链表长度超过8且数组长度>=64时,自动将链表自动转化为红黑树
深入理解HashSet去重机制
HashSet
不能对内容相同的两个不同对象进行去重!
内容相同的两个不同对象也能实现去重怎么操作?
如果希望set集合认为两个内容一样的不同对象是一样的,要重写hashCode和equals方法
package Collection;
import java.util.*;
public class _Set_ {
public static void main(String[] args) {
Set<Student> set=new HashSet<>();
set.add(new Student("孙悟空",999));
set.add(new Student("孙悟空",999));
set.add(new Student("孙悟空",999));
System.out.println(set.size());
}
}
class Student{
private String name;
private int age;
public Student() {
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public Student(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Student student = (Student) o;
return age == student.age && Objects.equals(name, student.name);
}
@Override
public int hashCode() {
return Objects.hash(name, age);
}
}
LinkedHashSet
有序、不重复、无索引
基于哈希表(数组、链表、红黑树)实现的,基本和HashSet相同,但是每个元素都额外多一个双链表的机制记录它前后元素的位置
TreeSet
不重复、无索引、自动排序(默认升序排序)
底层基于红黑树实现排序
- 对于数值类型(Integer、Double)默认按照数值大小排序
- 对于字符串类型,默认按照首字母排序
- 对于自定义类型,无法直接排序,要定义排序规则,两者同时存在的时候选构造器那个 也就是第一种方法
第一种方法:使用new Comparator
import java.util.Objects;
import java.util.Set;
import java.util.TreeSet;
public class _LinkedHashSet_ {
public static void main(String[] args) {
Set<Teacher>treeSet = new TreeSet<>((o1, o2) ->o1.getAge()-o2.getAge());
treeSet.add(new Teacher("送武汉",55));
treeSet.add(new Teacher("大苏打",55));//只会有一个55
treeSet.add(new Teacher("大苏打撒",35));
treeSet.add(new Teacher("的撒大",522));
System.out.println(treeSet);
}
}
class Teacher{
private String name;
private int age;
public Teacher() {
}
public String getName() {
return name;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Teacher teacher = (Teacher) o;
return age == teacher.age && Objects.equals(name, teacher.name);
}
@Override
public String toString() {
return "Teacher{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
@Override
public int hashCode() {
return Objects.hash(name, age);
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public Teacher(String name, int age) {
this.name = name;
this.age = age;
}
}
第二种方法:实现Comparable接口的compareTo
import java.util.Comparator;
import java.util.Objects;
import java.util.Set;
import java.util.TreeSet;
public class _LinkedHashSet_ {
public static void main(String[] args) {
Set<Teacher>treeSet = new TreeSet<>();
treeSet.add(new Teacher("送武汉",55));
treeSet.add(new Teacher("大苏打",55));//只会有一个55
treeSet.add(new Teacher("大苏打撒",35));
treeSet.add(new Teacher("的撒大",522));
System.out.println(treeSet);
}
}
class Teacher implements Comparable<Teacher> {
private String name;
private int age;
public Teacher() {
}
public String getName() {
return name;
}
@Override
public int compareTo(Teacher o){
return this.getAge()-o.getAge();
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Teacher teacher = (Teacher) o;
return age == teacher.age && Objects.equals(name, teacher.name);
}
@Override
public String toString() {
return "Teacher{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
@Override
public int hashCode() {
return Objects.hash(name, age);
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public Teacher(String name, int age) {
this.name = name;
this.age = age;
}
}
实际应用
- 需要记住添加顺序、存储重复元素、频繁的根据索引查询数据:
ArrayList
- 需要记住添加顺序、增删首位数据多:
LinkedArrayList
- 不在意添加顺序、不存储重复元素、增删改查要快:
HashSet
- 在意添加顺序、不存储重复元素、增删改查要快:
LinkedHashSet
- 对添加的元素排序、不存储重复元素、增删改查要快:
TreeSet
集合的并发修改异常问题
迭代器或者for循环可以处理这个问题
增强for和lambda表达式无法处理这个问题
package Collection;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
public class _Iterator {
public static void main(String[] args) {
List<String> list =new ArrayList<>();
list.add("李麻子");
list.add("麻李子");
list.add("王麻子");
list.add("张三");
Iterator<String> iterator = list.iterator();
while (iterator.hasNext()){
String name = iterator.next();
if (name.contains("李"))
iterator.remove();//删除迭代器当前遍历的数据 并且在底层也做了--i
}
for (String s : list) {
System.out.println(s);
}
}
}
Collections操作类
用于操作Collection的类
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
public class Collections_ {
public static void main(String[] args) {
List<String>names = new ArrayList<>();
//批量添加数据
Collections.addAll(names,"张三","李四","王五","刘六");
System.out.println(names);
//打乱List集合的顺序
Collections.shuffle(names);
System.out.println(names);
Collections.shuffle(names);
System.out.println(names);
//对List集合中元素进行排序
/*
* 对于自定义对象
* 1、类内实现comparable的compareTo
* 2、sort(List,new Comparator(){compare()})
* */
List<Integer>ids = new ArrayList<>();
Collections.addAll(ids,5,1,20,35,11,55);
System.out.println(ids);
Collections.sort(ids);
System.out.println(ids);
}
}
综合案例:斗地主游戏
仅完成洗牌、发牌
主程序类
public class Main {
public static void main(String[] args) throws Exception {
Room room = new Room();
room.showCards();
}
}
卡牌类
public class Card {
private String number;//牌的大小
private String color;//牌的花色
private int id;//牌真实的大小 比如 3<4<...<J<Q<k<A<2<🃏
public String getNumber() {
return number;
}
public String getColor() {
return color;
}
public int getId() {
return id;
}
public Card() {
}
public Card(String number, String color, int id) {
this.number = number;
this.color = color;
this.id = id;
}
@Override
public String toString() {
return color+number;
}
}
房间类
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Random;
import java.util.Scanner;
public class Room {
private final int CARD_COUNT = 54;
private final int PERSON_COUNT = 3;
private final List<Card> cards = new ArrayList<>(CARD_COUNT);//一副牌
private final List<Person>persons = new ArrayList<>(PERSON_COUNT);
public Room() throws Exception {
init();
start();
}
private void start() throws Exception {
while (true) {
shuffleCards();
sendCard();
if (selectLandlord()){
sortCard();
return;
}
clearCard();
}
}
private void init(){
String[] numbers={"3","4","5","6","7","8","9","10","J","Q","K","A","2"};
String[] colors = {"♠","♥","♦","♣"};
int id = 1;
for (String number : numbers) {
for (String color : colors) {
cards.add(new Card(number,color,id));
}
++id;
}
cards.add(new Card("","🃏",id++));
cards.add(new Card("","🤡",id));
String wanjia = "玩家";
for (int i = 0; i < PERSON_COUNT; i++) {
persons.add(new Person(wanjia+(i+1)));
}
}
private void shuffleCards(){
Collections.shuffle(cards);
// System.out.println("洗牌之后:"+cards);
}
private void sendCard(){
for (int i = 0; i < CARD_COUNT-3; i+=3) {
persons.get(0).setCard(cards.get(i));
persons.get(1).setCard(cards.get(i+1));
persons.get(2).setCard(cards.get(i+2));
}
}
private void clearCard(){
for (int i = 0; i < PERSON_COUNT; i++) {
persons.get(i).getCard().clear();
}
}
public void showCards(){
for (Person person : persons) {
if (person.isLandlord())
System.out.print("地主:");
else
System.out.print("农民:");
for (Card card : person.getCard())
System.out.print(" "+card.getNumber()+card.getColor()+" ");
System.out.println();
}
}
private boolean selectLandlord() throws Exception {
Random r = new Random();
int id = r.nextInt(0,3);
Scanner sc = new Scanner(System.in);
String res;
for (int i = 0; i < PERSON_COUNT; i++) {
Person person = persons.get((id+i)%3);
System.out.print(person.getName()+"是否选择做地主 y/n");
res = sc.next();
if (res.equals("y")){
person.setLandlord(true);
return true;
}
}
System.out.println("==游戏重新开始==");
Thread.sleep(3000);
return false;
}
private void sortCard(){
for (int i = 0; i < PERSON_COUNT; i++) {
persons.get(i).cardSort();
}
}
}
玩家类
import java.util.ArrayList;
import java.util.List;
public class Person {
private final List<Card>card = new ArrayList<>(20);
private boolean isLandlord;
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Person(String name) {
this.isLandlord = false;
this.name = name;
}
public boolean isLandlord() {
return isLandlord;
}
public void setLandlord(boolean landlord) {
isLandlord = landlord;
}
public List<Card> getCard() {
return card;
}
public void setCard(Card card){
this.card.add(card);
}
public void cardSort(){
card.sort(( o1, o2)->o2.getId()- o1.getId());
}
}
Map:双列集合
键值对集合 键不可重复
需要存储一一对应的数据可以考虑Map
特点:map系列的特点都是由键决定的,值不做要求 下面说的也都是依据键
HashMap
:无序、不重复、无索引(用的最多)LinkedHashMap
:有序、不重复、无索引TreeMap
:默认大小升序、不重复、无索引
Map常用的方法
import java.util.HashMap;
import java.util.Map;
public class demo {
public static void main(String[] args) {
Map<Integer,String> map = new HashMap<>();
map.put(4,"手表");
map.put(4,"手表2");
map.put(2,"java");
map.put(3,"C++");
map.put(null,null);
System.out.println(map);
//获取集合大小
System.out.println(map.size());
//清空集合
// map.clear();
//判断是否为空
System.out.println(map.isEmpty());
//根据key获取value 获取不存在的返回null
System.out.println(map.get(2));
System.out.println(map.get(1));
//根据key删除元素,并且返回对应的value
System.out.println(map.remove(2));
System.out.println(map);
//判断是否包含某个键
System.out.println(map.containsKey(2));
System.out.println(map.containsKey(3));
//判断是否包含某个值
System.out.println(map.containsValue("java"));
System.out.println(map.containsValue("C++"));
//获取Map的所有的键 返回Set<T>
for (Integer i : map.keySet()) {
System.out.print(i+" ");
}
System.out.println();
//获取Map的所有的值 返回Collection<T>
for (String value : map.values()) {
System.out.print(value+" ");
}
System.out.println();
//把其他map集合的数据倒入到自己的集合中 其他map不受影响
Map<Integer,String> map2 = new HashMap<>();
map2.put(1,"手表2");
map2.put(8,"手表2");
map2.put(2,"java");
map2.put(5,"C++");
map.putAll(map2);
System.out.println(map);
System.out.println(map2);
}
}
Map的遍历方式
- 键找值:获取Map集合的所有的键,再通过遍历键来找值
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
public class Demo2 {
public static void main(String[] args) {
Map<Integer,String> map = new HashMap<>();
map.put(1,"手表2");
map.put(8,"手表2");
map.put(2,"java");
map.put(5,"C++");
Set<Integer> mapKey = map.keySet();
for (Integer i : mapKey) {
System.out.println(i+"-"+map.get(i));
}
}
}
- 键值对:把“键值对”看成一个整体来遍历
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
public class Demo2 {
public static void main(String[] args) {
Map<Integer,String> map = new HashMap<>();
map.put(1,"手表2");
map.put(8,"手表2");
map.put(2,"java");
map.put(5,"C++");
//把map集合转换为键值对类型的set集合
//entries = [(key,value),(key,value)...]
Set<Map.Entry<Integer, String>> entries = map.entrySet();
for (Map.Entry<Integer, String> entry : entries) {
System.out.println(entry.getKey()+"-"+entry.getValue());
}
}
}
- Lambda
import java.util.HashMap;
import java.util.Map;
import java.util.function.BiConsumer;
public class Demo2 {
public static void main(String[] args) {
Map<Integer,String> map = new HashMap<>();
map.put(1,"手表2");
map.put(8,"手表2");
map.put(2,"java");
map.put(5,"C++");
map.forEach((key,value) ->System.out.println(key+"-"+value));
}
}
HashMap
底层原理
- HashMap和HashSet底层是一样的,HashSet内部就是HashMap缺一个泛型的
HashMap
不是并发 有线程安全问题- ConcurrentHashMap 可以处理并发的集合(没有线程安全问题)
基于哈希表,分JDK8之前和之后 存放的是一个entry
- 依赖hashCode和equals保证键的唯一性
LinkedHashMap
底层原理
-
LinkedHashMap和LinkedHashSet底层是一样的,LinkedHashSet内部就是LinkedHashMap缺一个泛型的
-
哈希表+双链表
-
存储的是
Entry
TreeMap
底层原理
- TreeMap和TreeSet底层是一样的,TreeSet内部就是TreeMap缺一个泛型的
- 红黑树
可变参数
一种特殊的形参,定义在方法、构造器的形参列表中,格式:数据类型 ... 参数名称
特点和好处
- 可以不传数据、可以传一个或者多个数据、可以传一个数组
- 灵活的接受数据
注意事项:
-
可变参数本质就是一个数组
-
一个形参列表只能有一个可变参数(可变参数唯一)
-
可变参数必须放在形参列表的最后
public class Test {
public static void main(String[] args) {
test(1);
test(10,20,30);
int[] arr={1,2,3,4,5,6};
test(arr);
}
public static void test(int ...datas){
//本质就是一个数组
System.out.println(Arrays.toString(datas));
}
}
File、IO流
File类
File
是java.io.
包下的类,File
类的对象用于表示当前操作系统的文件、文件夹
代表文件,获取文件大小、创建时间等等等
**注意:**File类只能对文件本身进行操作,不能读写文件里面存储的数据
File常用方法
import java.io.File;
public class Demo1 {
public static void main(String[] args) {
//1、创建一个File对象 指代某个具体文件
File file1 = new File("D:\\复试-毕设\\demo.txt");
File file2 = new File("D:/复试-毕设/demo.txt");
File file3 = new File("D:"+File.separator+"复试-毕设"+File.separator+"demo.txt");
//文件夹
File file4= new File("D:\\复试-毕设");
//指向不存在的文件
File file5= new File("D:\\复试毕设\\a.txt");
//文件在模块
File file6 = new File("javaSEstudy\\src\\yb0os1.txt");
System.out.println(file6.exists());
System.out.println(file5.exists());
System.out.println(file1.length());//文件大小 字节
System.out.println(file4.length());
}
}
import java.io.File;
import java.text.SimpleDateFormat;
public class Demo2 {
public static void main(String[] args) {
File file = new File("D:\\code\\javaCodes\\javaSEstudy\\src\\yb0os1.txt");
System.out.println(file.exists());//是否存在
System.out.println(file.isFile());//是否为文件
System.out.println(file.getName());//文件名称
System.out.println(file.length());//文件大小 字节
long time = file.lastModified();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
System.out.println(sdf.format(time));
System.out.println(file.lastModified());//最后修改时间 时间毫秒值
System.out.println(file.getPath());//创建文件对象时使用的路径
System.out.println(file.getAbsolutePath());//创建文件对象时使用的绝对路径
}
}
import java.io.File;
import java.io.IOException;
public class Demo3 {
public static void main(String[] args) throws IOException {
File file = new File("./src/yb0os1.txt");
//创建新文件 文件内容为空 创建成功返回true
if (!file.exists())file.createNewFile();
else System.out.println("失败");
//创建一级文件夹
File file2 = new File("./yb0os1");
System.out.println(file2.mkdir());
//创建多级文件夹
File file3 = new File("D:\\code\\aaa\\dad");
System.out.println(file2.mkdirs());
//删除文件或者空文件 不能删除非空文件夹
file2.delete();
}
}
import java.io.File;
public class Demo4 {
public static void main(String[] args) {
File file = new File("D:\\code");
//获取当前目录下所有的一级文件名字
for (String s : file.list()) {
System.out.println(s);
}
//(重点)获取当前目录下所有的"一级文件对象"到一个文件对象数组中去返回(重点)
File[] files = file.listFiles();
for (File file1 : files) {
System.out.println(file1.getAbsolutePath());
}
}
}
IO流
用于读写数据(文件、网络数据…)
编码、解码
import java.io.UnsupportedEncodingException;
import java.util.Arrays;
public class Demo6 {
public static void main(String[] args) throws UnsupportedEncodingException {
String data = "1a好好";
byte[] bytes = data.getBytes();//默认按照平台字符集
System.out.println(Arrays.toString(bytes));
byte[] bytes1 = data.getBytes("GBK");//指定字符集编码
System.out.println(Arrays.toString(bytes1));
String data1 = new String(bytes);//默认按照平台字符集
System.out.println(data1);
String data2 = new String(bytes1,"GBK");
System.out.println(data2);
}
}
分类
- 字节输入流:输入内存中
- 字节输出流:从内存中输出到磁盘、网络
- 字符输入流:以字符为基本单位
- 字符输出流:以字符为基本单位
文件字节流
文件字节输入流:FileInputStream
以内存为基准,可以把磁盘文件中的数据以一个一个字节的形式读入到内存中
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.IOException;
public class Demo7 {
public static void main(String[] args) throws IOException {
InputStream fileInputStream = new FileInputStream("./src/yb0os1.txt");
InputStream fileInputStreamC = new FileInputStream(new File("./src/yb0os1.txt"));
int b;
//一个一个字节的读取数据
while ((b = fileInputStream.read()) != -1){
System.out.print((char) b);
}
}
}
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.IOException;
public class Demo7 {
public static void main(String[] args) throws IOException {
InputStream fileInputStream = new FileInputStream("./src/yb0os1.txt");
byte[]buffer = new byte[3];
int len;//记录每次读取了多少个字节 性能提高
while ( (len = fileInputStream.read(buffer))!=-1){
//这种方式也可能存在汉字乱码的问题
System.out.print(new String(buffer,0,len));
}
fileInputStream.close();
}
}
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.IOException;
public class Demo7 {
public static void main(String[] args) throws IOException {
//1、一次性读完一个文件 不适用文件特别大的情况 超过2^31-1
/* File file = new File("./src/yb0os1.txt");
InputStream is = new FileInputStream(file);
byte[]buffer = new byte[(int) file.length()];
int read = is.read(buffer);
String s = new String(buffer, 0, read);
System.out.println(s);
is.close();
*/
//2、调用方法 readAllBytes 不适用文件特别大的情况
InputStream is = new FileInputStream("./src/yb0os1.txt");
byte[]buffer = is.readAllBytes();
String s = new String(buffer);
System.out.println(s);
is.close();
}
}
注意事项
- read读取数据效率比较差,一个一个字节读取,读取系统硬件资源比较多
- 读取汉字会乱码,而且无法避免
- 流使用完毕要关闭
文件字节输出流:FileOutputStream
把内存数据写入到磁盘文件
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Arrays;
public class Demo8 {
public static void main(String[] args) throws IOException {
//默认为覆盖管道
// OutputStream os = new FileOutputStream("./src/ying.txt");
//追加管道
OutputStream os = new FileOutputStream("./src/ying.txt",true);
os.write('d');//写入一个字节
os.write('u');//写入一个字节
os.write("我爱你中国ing".getBytes());//写入一个字节数组
os.write("我爱你中国ing".getBytes(),0,15);//写入一个字节数组的一部分
os.write("\r\n".getBytes());//在任何系统都是换行
os.close();
}
}
文件复制
字节流适合文件复制、剪切等
package _File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
public class FileCopy {
public static void main(String[] args) throws IOException {
InputStream is = new FileInputStream("D:\\复试-毕设\\微信图片_20240306085505.png");
OutputStream os = new FileOutputStream("./src/shangan.png");
byte[] buffer = new byte[1024];
int len;
while ((len = is.read(buffer))!=-1){
os.write(buffer,0,len);
}
//一般就是后创建的先关闭
os.close();
is.close();
}
}
资源释放的方式
- try-catch-finally:finally代码区的特点:无论try中的程序是正常执行了,还是出现了异常,最后都一定会执行finally区,除非IVM终止。
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
public class FileCopy {
public static void main(String[] args) {
InputStream is = null;
OutputStream os = null;
try {
is = new FileInputStream("D:\\复试-毕设\\微信图片_20240306085505.png");
os = new FileOutputStream("./src/shangan.png");
byte[] buffer = new byte[1024];
int len;
while ((len = is.read(buffer)) != -1) {
os.write(buffer, 0, len);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
//释放资源的操作
try {
if(os!=null)os.close();
} catch (IOException e) {
e.printStackTrace();
}
try {
if(is!=null)is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
- try-with-resource:上述代码臃肿,JDK7开始可以使用
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
public class FileCopy {
public static void main(String[] args) {
try (//括号内部只能定义资源变量 资源都会实现 AutoCloseable 接口
//资源放在括号内,使用完后会自动调用close方法
InputStream is = new FileInputStream("D:\\复试-毕设\\微信图片_20240306085505.png");
OutputStream os = new FileOutputStream("./src/shangan.png")) {
byte[] buffer = new byte[1024];
int len;
while ((len = is.read(buffer)) != -1) {
os.write(buffer, 0, len);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
文件字符流
读写建议字符流
文件字符输入流:FileReader
以内存为基准,可以把文件中的数据以字符的形式读入到内存中去
import java.io.FileReader;
public class Demo9 {
public static void main(String[] args) {
try( //1、创建一个文件字符输入流管道与源文件接通
FileReader fr = new FileReader("./src/yb0os1.txt"); ){
//2、读取文本的内容
/*int c;
while ((c=fr.read())!=-1){
System.out.print((char) c);//每次读取一个字符,性能比较差
}*/
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();
}
}
}
文件字符输出流:FileWriter
以内存为基准,把内存中的数据以字符的形式写出到文件中去。
import java.io.FileWriter;
import java.io.Writer;
public class Demo10 {
public static void main(String[] args) {
try (Writer writer = new FileWriter("./src/lll.txt");) {
writer.write('c');
writer.write('中');
writer.write("你好啊");
writer.write("\r\n");
writer.write("我爱你中国",0,3);
char[]buffer = {'a','b','c'};
writer.write(buffer);
} catch (Exception e) {
e.printStackTrace();
}
}
}
字符输出流写出数据后,必须刷新流或者关闭流,写出去的数据才能生效
关闭包含刷新
缓冲流
对原始流进行包装,提高原始流读写数据的性能
字节缓冲流
提高字节流读写数据的效率
原理:字节缓冲输入/输出流自带8KB缓冲流
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
public class Demo11 {
public static void main(String[] args) {
try (//括号内部只能定义资源变量 资源都会实现 AutoCloseable 接口
//资源放在括号内,使用完后会自动调用close方法
InputStream is = new FileInputStream("D:\\复试-毕设\\微信图片_20240306085505.png");
InputStream bis = new BufferedInputStream(is);//可以指定buffer的大小
OutputStream os = new FileOutputStream("./src/shangan.png");
OutputStream bos = new BufferedOutputStream(os);
) {
byte[] buffer = new byte[1024];
int len;
while ((len = bis.read(buffer)) != -1) {
bos.write(buffer, 0, len);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
字符缓冲流
自**带8K(8192)**的缓冲池
外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传](https://img-home.csdnimg.cn/images/20230724024159.png?origin_url=C%3A%5CUsers%5Clneovo%5CAppData%5CRoaming%5CTypora%5Ctypora-user-images%5Cimage-20240430233654838.png&pos_id=img-hRVCXqub-1716375401455)
![外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.Reader;
public class Demo12 {
public static void main(String[] args) {
try( Reader is = new FileReader("./src/yb0os1.txt");
BufferedReader br = new BufferedReader(is);
){
/*String data = null;
while ((data=br.readLine())!=null){
System.out.println(data);
}*/
char[]buffer = new char[3];
int len;
while ((len = br.read(buffer))!=-1){
System.out.print(new String(buffer,0,len));
}
}catch (Exception e){
e.printStackTrace();
}
}
}
原始流、缓冲流的性能分析
package _File;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
public class Test {
private final static String SRC_FILE = "E:\\学习资料\\java.mp4";
private final static String DESC_FILE = "D:\\";
public static void main(String[] args) {
// copy1();//太慢了 等不起
copy2();//5.485s 字节数组1024*8 -》 0.846s
// copy3();//3.887s 淘汰
copy4();//0.83s 字节数组1024*8 -》 0.82s == 推荐使用
}
private static void copy1() {
long startTime = System.currentTimeMillis();
try (
InputStream is = new FileInputStream(SRC_FILE);
OutputStream os = new FileOutputStream(DESC_FILE + "1.mp4");
) {
int c;
while ((c = is.read()) != -1) {
os.write(c);
}
} catch (Exception x) {
x.printStackTrace();
}
long endTime = System.currentTimeMillis();
System.out.println("原始流:一个一个字节拷贝:" + (endTime - startTime) / 1000.0 + "s");
}
private static void copy2() {
long startTime = System.currentTimeMillis();
try (
InputStream is = new FileInputStream(SRC_FILE);
OutputStream os = new FileOutputStream(DESC_FILE + "2.mp4");
) {
byte[] buffer = new byte[1024*8];
int len;
while ((len = is.read(buffer)) != -1) {
os.write(buffer, 0, len);
}
} catch (Exception x) {
x.printStackTrace();
}
long endTime = System.currentTimeMillis();
System.out.println("原始流:字节数组1024拷贝:" + (endTime - startTime) / 1000.0 + "s");
}
private static void copy3() {
long startTime = System.currentTimeMillis();
try (
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(SRC_FILE));
BufferedOutputStream ois = new BufferedOutputStream(new FileOutputStream(DESC_FILE + "3.mp4"));
) {
int c;
while ((c = bis.read()) != -1) {
ois.write(c);
}
} catch (Exception x) {
x.printStackTrace();
}
long endTime = System.currentTimeMillis();
System.out.println("缓冲流:一个一个字节拷贝:" + (endTime - startTime) / 1000.0 + "s");
}
private static void copy4() {
long startTime = System.currentTimeMillis();
try (
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(SRC_FILE));
BufferedOutputStream ois = new BufferedOutputStream(new FileOutputStream(DESC_FILE + "4.mp4"));
) {
byte[] buffer = new byte[1024*8];
int len;
while ((len = bis.read(buffer)) != -1) {
ois.write(buffer, 0, len);
}
} catch (Exception x) {
x.printStackTrace();
}
long endTime = System.currentTimeMillis();
System.out.println("缓冲流:字节数组1024拷贝:" + (endTime - startTime) / 1000.0 + "s");
}
}
字节数组并非越大越好
转换流
如果代码编码和文本文件编码一致,那么字符流读取文本文件不会乱码
如果代码编码和文本文件编码不一致,那么字符流读取文本文件会乱码
字符输入转换流 InputStreamReader
字节->字符
先获取文件的原始字节流,再将其按真实的字符集编码转成字符输入流,这样字符输入流中的字符就不乱码
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
public class Demo15 {
public static void main(String[] args) {
try(
//获取原始字节流
InputStream is = new FileInputStream("./src/llll.txt");
//按照GBK转为字符输入流
Reader ris = new InputStreamReader(is,"GBK");
BufferedReader br = new BufferedReader(ris);
){
String line;
while ((line=br.readLine())!=null){
System.out.println(line);
}
}catch (Exception e){
e.printStackTrace();
}
}
}
字符输出转换流 OuputStreamWriter
控制写出去的字符使用什么字符集编码
字节->字符
获取字节输出流,再按照指定的字符集编码将其转换成字符输出流,以后写出去的字符就会用该字符集编码了
import java.io.BufferedWriter;
import java.io.FileOutputStream;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.Writer;
public class Demo16 {
public static void main(String[] args) {
try(
OutputStream os = new FileOutputStream("./src/xx.txt");
Writer w = new OutputStreamWriter(os,"GBK");
BufferedWriter bw = new BufferedWriter(w);
){
bw.write("你好呀中国");
bw.newLine();
}catch (Exception e){
e.printStackTrace();
}
}
}
打印流
可以实现更方便、更高效的打印数据出去,能实现打印啥就是啥
PrintStream
import java.io.PrintStream;
import java.nio.charset.Charset;
public class Demo17 {
public static void main(String[] args) {
try (PrintStream ps = new PrintStream("./src/xx.txt", Charset.forName("GBK"));){
ps.println(55);
ps.println('d');
ps.println("dadsada");
ps.println("年后啊");
} catch (Exception e) {
e.printStackTrace();
}
}
}
PrintWriter
区别
- 打印数据的功能上是一模一样的:都是使用方便,性能高效(核心优势)
- PrintStream继承自字节输出流OutputStream,因此支持写字节数据的方法。
- PrintWriter继承自字符输出流Writer,因此支持写字符数据出去
打印数据重定向
import java.io.FileOutputStream;
import java.io.PrintStream;
public class Demo18 {
public static void main(String[] args) {
System.out.println("yb0os1");
try (PrintStream ps = new PrintStream(new FileOutputStream("./src/yb0os1.txt",true));){
System.setOut(ps);
System.out.println("yb0os1");
} catch (Exception e) {
e.printStackTrace();
}
}
}
数据流
允许把数据和其类型一并写出去
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
public class Demo19 {
public static void main(String[] args) {
try(
DataOutputStream dps= new DataOutputStream(new FileOutputStream("./src/yb0os1.txt"));
DataInputStream dis = new DataInputStream(new FileInputStream("./src/yb0os1.txt"))
) {
dps.writeInt(15);
dps.writeDouble(19.5);
dps.writeUTF("我爱中国");
//相对应的读取
int a = dis.readInt();
double b = dis.readDouble();
String c = dis.readUTF();
System.out.println(a);
System.out.println(b);
System.out.println(c);
} catch (Exception e) {
e.printStackTrace();
}
}
}
序列化流
把对象写入文件
序列化和反序列化
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
public class Demo20 {
public static void main(String[] args) {
try(
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("./src/yb0os1.txt"));
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("./src/yb0os1.txt"));
){
User u = new User(2001,"张三",18,178.5);
oos.writeObject(u);//序列化 写入文件
User user = (User) ois.readObject();//反序列化
System.out.println(user.getId());
System.out.println(user.getAge());
}catch (Exception e){
e.printStackTrace();
}
}
}
//对象要序列化必须实现序列化接口 Serializable
class User implements Serializable {
private transient int id;//不会被序列化
private String name;
private int age;
private double height;
public User() {
}
public User(int id, String name, int age, double height) {
this.id = id;
this.name = name;
this.age = age;
this.height = height;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public double getHeight() {
return height;
}
public void setHeight(double height) {
this.height = height;
}
}
IO框架
Commons-io
import org.apache.commons.io.FileUtils;
import java.io.File;
import java.io.IOException;
public class Demo21 {
public static void main(String[] args) throws IOException {
FileUtils.copyFile(new File("./src/llll.txt"),new File("./src/l.txt"));
FileUtils.delete(new File("./src/l.txt"));
System.out.println(FileUtils.readFileToString(new File("./src/yb0os1.txt"), "GBK"));
}
}
特殊文本文件、日志技术
特殊文本文件
属性文件 properties
![外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传](https://img-blog.csdnimg.cn/direct/44eb4a8771384565accacb5c3531a9a7.png)
import java.io.FileReader;
import java.io.FileWriter;
import java.util.Properties;
public class Demo1 {
public static void main(String[] args) throws Exception {
Properties properties = new Properties();
properties.load(new FileReader("./src/users.properties"));
System.out.println(properties.getProperty("yb0os1"));//根据键去值
//遍历所有的键值
for (String s : properties.stringPropertyNames()) {
System.out.println(s+"-"+properties.getProperty(s));
}
properties.forEach((k,v)-> System.out.println(k+"-"+v));
properties.setProperty("hhh","yyy");
properties.setProperty("xxx","qqq");
properties.setProperty("sss","aaaa");
properties.store(new FileWriter("./src/users.properties"),"users");
}
}
XML文件
XML可扩展标记语言,一种特殊的数据格式,可以用来存储复杂的数据类型和数据关系
应用场景:系统的配置文件、在网络上传输
使用第三方框架 Dom4j 解析XML文件
import org.dom4j.Attribute;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import java.util.List;
/**
* Dom4j解析XML文件:文档对象模型
*/
public class Demo2 {
public static void main(String[] args) throws DocumentException {
//1、创建一个Dom4J框架提供的解析器对象
SAXReader saxReader = new SAXReader();
//2、使用SAXReader将解析的XML读取为document
Document document = saxReader.read("./src/data.xml");
//3、从文档对象中解析XML文件的全部数据
Element rootElement = document.getRootElement();
List<Element> elements = rootElement.elements();
// List<Element> elements = rootElement.elements("user");
Element element = rootElement.element("person");//多个person的话取第一个
System.out.println(element.getText());
Element user = rootElement.element("user");
Attribute id = user.attribute("id");
System.out.println(id.getName());
System.out.println(id.getValue());
System.out.println(user.elementText("name"));
System.out.println(user.elementText("age"));
System.out.println(user.elementTextTrim("data"));
}
}
将数据写入XML文件
import java.io.BufferedWriter;
import java.io.FileWriter;
public class Demo3 {
public static void main(String[] args) {
try(
BufferedWriter bw = new BufferedWriter(new FileWriter("./src/books.xml"));
) {
StringBuffer str = new StringBuffer();
str.append("<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\r\n");
str.append("<books>\r\n");
str.append("\t<book id=\"1\">\r\n");
str.append("\t\t<name>").append("java高级开发").append("</name>\r\n");
str.append("\t\t<price>").append("52.6").append("</price>\r\n");
str.append("\t\t<author>").append("yb0os1").append("</author>\r\n");
str.append("\t</book>\r\n");
str.append("\t<book id=\"2\">\r\n");
str.append("\t\t<name>").append("C/C++").append("</name>\r\n");
str.append("\t\t<price>").append("78.6").append("</price>\r\n");
str.append("\t\t<author>").append("yb0os1").append("</author>\r\n");
str.append("\t\t</book>\r\n");
str.append("</books>");
bw.write(str.toString());
} catch (Exception e) {
e.printStackTrace();
}
}
}
约束XML文件的书写格式:约束文档
分类
- DTD约束文档
DTD不能约束具体的数据类型
- schema约束文档
日志技术
概述
-
记录程序运行过程中的各种信息
-
可以将系统执行的信息,方便的记录到指定的位置(控制台、文件中、数据库中)
-
可以随时以开关的形式控制日志的启停,无需侵入到源代码中去进行修改,
日志技术体系结构
Logback是基于slf4j实现的
项目中使用logback至少整合:
- slf4j-api 日志接口
- logback-core
- logback-classic
logback快速入门
步骤:
- 导入logback框架到项目
- slf4j-api 日志接口
- logback-core
- logback-classic
- 将logback框架的核心配置文件logback.xml直接拷贝到src下面(必须是src下面)
- 创建logback框架提供的Logger对象,然后使用Logger对象调用其提供的方法就可以记录系统的日志信息了
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class LogBackTest {
public static final Logger LOGGER = LoggerFactory.getLogger("LogBackTest");
public static void main(String[] args) {
try {
LOGGER.info("进行除法~~~~~");
chu(12,0);
LOGGER.info("除法完成~~~~~");
}catch (Exception e){
LOGGER.error("除法执行失败");
}
}
public static void chu(int a,int b){
LOGGER.debug("参数a:"+a);
LOGGER.debug("参数b:"+b);
// System.out.println(a/b);
LOGGER.info("结果是:"+(a/b));
}
}
logback.xml 核心配置文件
对logback日志框架进行控制
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<!--
CONSOLE :表示当前的日志信息是可以输出到控制台的。
appender 控制日志输入到那里去
-->
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<!--输出流对象 默认 System.out 改为 System.err-->
<target>System.out</target>
<encoder>
<!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度
%msg:日志消息,%n是换行符-->
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%-5level] %c [%thread] : %msg%n</pattern>
</encoder>
</appender>
<!-- File是输出的方向通向文件的 -->
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
<charset>utf-8</charset>
</encoder>
<!--日志输出路径-->
<file>./logs/data.log</file>
<!--指定日志文件拆分和压缩规则-->
<rollingPolicy
class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<!--通过指定压缩文件名称,来确定分割文件方式-->
<fileNamePattern>./logs/data-%i-%d{yyyy-MM-dd}-.log.gz</fileNamePattern>
<!--文件拆分大小
就是当日志文件大小达到1MB,将这个文件压缩新的日志文件
-->
<maxFileSize>1MB</maxFileSize>
</rollingPolicy>
</appender>
<!--
1、控制日志的输出情况:如,开启日志,取消日志
ALL开启日志 OFF 关闭日志
-->
<root level="ALL">
<appender-ref ref="CONSOLE"/><!-- 当不想输出到控制台的时候,关闭这个就行 -->
<appender-ref ref="FILE" />
</root>
</configuration>