Java基础(二)- 异常、集合、IO流、特殊文件、日志

异常

认识异常

异常就是程序出现的问题

在这里插入图片描述

自定义异常

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));
        }
    }
}

ArrayListLinkedList底层数据结构不同

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类

Filejava.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>

logback日志级别

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值