- 特殊文件
- Properties属性文件
- 可以很方便的存储一些类似于键值对的数据。经常当做软件的配置文件使用。
- 属性文件里面的每一行都是一个键值对,键和值中间用=隔开。比如: admin=123456
- #表示这样是注释信息,是用来解释这一行配置是什么意思
- 每一行末尾不要习惯性加分号,以及空格等字符;不然会把分号,空格会当做值的一部分。
- 键不能重复,值可以重复、
- 可以使用Properties读取属性文件中的键值对
- Properties是Map接口下面的一个实现类,所以Properties也是一种双列集合,用来存储键值对。 但是一般不会把它当做集合来使用。
- Properties类的对象,用来表示属性文件,可以用来读取属性文件中的键值对。
- Properties属性文件
/**
* 目标:掌握使用Properties类读取属性文件中的键值对信息。
*/
public class PropertiesTest1 {
public static void main(String[] args) throws Exception {
// 1、创建一个Properties的对象出来(键值对集合,空容器)
Properties properties = new Properties();
System.out.println(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);
});
}
}
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!");
}
}
- XML文件
- 能够表示更加复杂的数据关系,比如要表示多个用户的用户名、密码、家乡、性别等。在后面,也经常当做软件的配置文件使用。
<?xml version="1.0" encoding="UTF-8" ?>
<!-- 注释:以上抬头声明必须放在第一行,必须有 -->
<!-- 根标签只能有一个 -->
<users>
<user id="1" desc="第一个用户">
<name>张无忌</name>
<sex>男</sex>
<地址>光明顶</地址>
<password>minmin</password>
</user>
<people>很多人</people>
<user id="2">
<name>敏敏</name>
<sex>女</sex>
<地址>光明顶</地址>
<password>wuji</password>
</user>
</users>
2. XML解析:Dom4J
public class Dom4JTest1 {
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();
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");
System.out.println(user.elementText("name"));
// 6、获取元素的属性信息呢?
System.out.println(user.attributeValue("id"));
Attribute id = user.attribute("id");
System.out.println(id.getName());
System.out.println(id.getValue());
List<Attribute> attributes = user.attributes();
for (Attribute attribute : attributes) {
System.out.println(attribute.getName() + "=" + attribute.getValue());
}
// 7、如何获取全部的文本内容:获取当前元素下的子元素文本值
System.out.println(user.elementText("name"));
System.out.println(user.elementText("地址"));
System.out.println(user.elementTextTrim("地址")); // 取出文本去除前后空格
System.out.println(user.elementText("password"));
Element data = user.element("data");
System.out.println(data.getText());
System.out.println(data.getTextTrim()); // 取出文本去除前后空格
}
}
3. XML写入
public class Dom4JTest2 {
public static void main(String[] args) {
// 1、使用一个StringBuilder对象来拼接XML格式的数据。
StringBuilder sb = new StringBuilder();
sb.append("<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\r\n");
sb.append("<book>\r\n");
sb.append("\t<name>").append("从入门到跑路").append("</name>\r\n");
sb.append("\t<author>").append("dlei").append("</author>\r\n");
sb.append("\t<price>").append(999.99).append("</price>\r\n");
sb.append("</book>");
try (
BufferedWriter bw = new BufferedWriter(new FileWriter("properties-xml-log-app/src/book.xml"));
){
bw.write(sb.toString());
} catch (Exception e) {
e.printStackTrace();
}
}
}
- 日志
- 记录了程序运行过程中产生的各种数据。
- 日志框架:Logback
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);
}
}
- 日志级别
- Logback只输出大于或者等于核心配置文件配置的日志级别信息。小于配置级别的日志信息,不被记录。
- 配置的是trace,则trace、debug、info、warn、error级别的日志都被输出
- 配置的是debug, 则debug、info、warn、error级别的日志被输出
- 配置的是info,则info、warn、error级别的日志被输出
- 多线程
- 创建线程1:继承Thread
1.定义一个子类继承Thread类,并重写run方法
2.创建Thread的子类对象
3.调用start方法启动线程(启动线程后,会自动执行run方法中的代码)
public class MyThread extends Thread{
// 2、必须重写Thread类的run方法
@Override
public void run() {
// 描述线程的执行任务。
for (int i = 1; i <= 5; i++) {
System.out.println("子线程MyThread输出:" + i);
}
}
}
public class ThreadTest1 {
// main方法是由一条默认的主线程负责执行。
public static void main(String[] args) {
// 3、创建MyThread线程类的对象代表一个线程
Thread t = new MyThread();
// 4、启动线程(自动执行run方法的)
t.start();
for (int i = 1; i <= 5; i++) {
System.out.println("主线程main输出:" + i);
}
}
}
- 创建线程2:实现Runnable接口
1.先写一个Runnable接口的实现类,重写run方法(这里面就是线程要执行的代码)
2.再创建一个Runnable实现类的对象
3.创建一个Thread对象,把Runnable实现类的对象传递给Thread
4.调用Thread对象的start()方法启动线程(启动后会自动执行Runnable里面的run方法)
/**
* 1、定义一个任务类,实现Runnable接口
*/
public class MyRunnable implements Runnable{
// 2、重写runnable的run方法
@Override
public void run() {
// 线程要执行的任务。
for (int i = 1; i <= 5; i++) {
System.out.println("子线程输出 ===》" + i);
}
}
}
public class ThreadTest2 {
public static void main(String[] args) {
// 3、创建任务对象。
Runnable target = new MyRunnable();
// 4、把任务对象交给一个线程对象处理。
// public Thread(Runnable target)
new Thread(target).start();
for (int i = 1; i <= 5; i++) {
System.out.println("主线程main输出 ===》" + i);
}
}
}
- 创建线程3:直接创建Runnable接口的匿名内部类对象
public class ThreadTest2_2 {
public static void main(String[] args) {
// 1、直接创建Runnable接口的匿名内部类形式(任务对象)
Runnable target = new Runnable() {
@Override
public void run() {
for (int i = 1; i <= 5; i++) {
System.out.println("子线程1输出:" + i);
}
}
};
new Thread(target).start();
// 简化形式1:
new Thread(new Runnable() {
@Override
public void run() {
for (int i = 1; i <= 5; i++) {
System.out.println("子线程2输出:" + i);
}
}
}).start();
// 简化形式2:
new Thread(() -> {
for (int i = 1; i <= 5; i++) {
System.out.println("子线程3输出:" + i);
}
}).start();
for (int i = 1; i <= 5; i++) {
System.out.println("主线程main输出:" + i);
}
}
}
- 创建线程4:
1.先定义一个Callable接口的实现类,重写call方法
2.创建Callable实现类的对象
3.创建FutureTask类的对象,将Callable对象传递给FutureTask
4.创建Thread对象,将Future对象传递给Thread
5.调用Thread的start()方法启动线程(启动后会自动执行call方法)
等call()方法执行完之后,会自动将返回值结果封装到FutrueTask对象中
6.调用FutrueTask对的get()方法获取返回结果
import java.util.concurrent.Callable;
import java.util.concurrent.FutureTask;
// Step 1: 实现 Callable 接口
class MyCallable implements Callable<Integer> {
@Override
public Integer call() throws Exception {
int result = 0;
for (int i = 1; i <= 10; i++) {
result += i;
}
return result;
}
}
public class Main {
public static void main(String[] args) {
// Step 2: 创建 Callable 实现类的对象
Callable<Integer> callable = new MyCallable();
// Step 3: 创建 FutureTask 对象,将 Callable 对象传递给 FutureTask
FutureTask<Integer> futureTask = new FutureTask<>(callable);
// Step 4: 创建 Thread 对象,将 Future 对象传递给 Thread
Thread thread = new Thread(futureTask);
// Step 5: 调用 Thread 的 start() 方法启动线程
thread.start();
// Step 6: 调用 FutureTask 的 get() 方法获取返回结果
try {
Integer result = futureTask.get(); // 这里会阻塞,直到线程执行完毕并返回结果
System.out.println("线程执行结果:" + result);
} catch (Exception e) {
e.printStackTrace();
}
}
}