Java学习之IO流


IO流:用来进行设备间的数据传输问题;输入流:读入数据,输出流:写数据;如果数据是文本类型的我们可以使用字符流来处理

字节流(InputStream,OutputStream)

  • outputStream:表示输出字节流的所有类的超类,输出流接受输出字节并将这些字节发送到每个接收器

FileOutputStream

  • FileOutputStream: 用于写入诸如图像数据的原始字节流.
/*
 * FileOutPutStream的构造方法;
 * FileOutputStream(File file): 创建文件输出流以写入由指定的 File对象表示的文件。
 * FileOutputStream(String name):创建文件输出流以指定的名称写入文件。
 * 上述两个构造方法的效果是一样的,前者传递文件 后者传递文件路径名称
 * 
 * 
 * 
 * FileOutputStream(File file, boolean append) :创建文件输出流以写入由指定的 File对象表示的文件。
 * FileOutputStream(String name, boolean append):创建文件输出流以指定的名称写入文件。
 * 上述这个两个构造方法也是一样的  第二个参数表示是够在文件的本来的内容后面追加内容
 * 
 * 
 * FileOutputStream(FileDescriptor fdObj):创建文件输出流以写入指定的文件描述符,表示与文件系统中实际文件的现有连接。
 * 
 * 
 * 字节输出流操作步骤:
 * 		1.创建字节流对象
 * 		2.写数据
 * 		3.释放资源
 * 
 */
public static void writerFile2(String tempFileName, boolean append) {
		// 2.首先我们先创建一个输出流
		OutputStream fileOutputStream = null;
		// 该构造方法和上面文件参数创建的效果是一样的
		// OutputStream fileOutputStream2 = new FileOutputStream("test.text");
		try {
			fileOutputStream = new FileOutputStream(tempFileName, append);
			/**
			 * 创建字节流对象做了几件事情
			 * 1.调用系统功能去创建文件
			 * 2.创建 fileOutputStream (输入流对象)对象
			 * 3.把fileOutputStream对象指向这个文件
			 */
			fileOutputStream.write("GY hello world java".getBytes());
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO: handle exception
			e.printStackTrace();
		} finally {
			// 释放资源 关闭此文件输出流并释放此流有关的所有系统资源。
			// 如果该对象是null我们就不需要释放
			if (fileOutputStream != null) {
				try {
					/*
					 * 为什么一定要close()?
					 * 
					 * 1.让流对象编程垃圾,这样就可以被垃圾回收器回收了
					 * 2.通知系统去释放该文件的相关资源
					 */
					fileOutputStream.close();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}
	}
	
	
	/*
	 * 文件写入内容
	 */
	public static void writerFile(String tempFileName) {

		// 2.首先我们先创建一个输出流
		OutputStream fileOutputStream = null;
		// 该构造方法和上面文件参数创建的效果是一样的
		// OutputStream fileOutputStream2 = new FileOutputStream("test.text");
		try {
			fileOutputStream = new FileOutputStream(tempFileName);
			fileOutputStream.write("hello world java".getBytes());
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO: handle exception
			e.printStackTrace();
		} finally {
			// 释放资源
			if (fileOutputStream != null) {
				try {
					fileOutputStream.close();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}
	}

FileInputStream

  • FileInputStream: 用于读取诸如图像数据的原始字节流
/*
	 * 一次读取多个字节的方法
	 */
	public static void readFileContent(String fileNamPath) {
		FileInputStream fileInputStream = null;
		
		try {
			fileInputStream = new FileInputStream(fileNamPath);
			//从文件中读取数据
			//创建一个类似缓冲区的字节数组,一次读取2014个字节,缓冲区长度一般是1024或则是1024的整数倍
			byte[] fileString = new byte[10];
			int len = 0;
			//判断读取的
			while ((len = fileInputStream.read(fileString)) != -1) {
//				System.out.println("len ===" + len + "fileString.length=====" + fileString.length);
				System.out.println(new String(fileString, 0, len));
			}
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
	}

BufferedOutputStream

  • BufferedOutputStream: 高效字节输出流
/*
	 * 使用字符缓存输入流 来写写入内容到文件(高效类)
	 * 
	 * bufferedOutputStream类
	 */
	public static void writerForBuffered(String fileName) {
		// 创建一个字节缓冲输入流对象
		BufferedOutputStream bufferedOutputStream = null;
		try {
			bufferedOutputStream = new BufferedOutputStream(new FileOutputStream(fileName));
			bufferedOutputStream.write("我正在学历Java中的IO流".getBytes());
		} catch (IOException e) {
			// TODO: handle exception
			e.printStackTrace();
		}finally {
			if (bufferedOutputStream != null) {
				try {
					bufferedOutputStream.close();
				} catch (IOException e2) {
					// TODO: handle exception
					e2.printStackTrace();
				}
			}
		}
	}

BufferedInputStream

  • BufferedInputStream:高效字节输入流
/*
	 * 高效类 字节缓冲输入流  (高效字节流)
	 * 
	 * BufferedInputStream
	 */
	public static void readerForBuffuered(String fileName) {
		BufferedInputStream bufferedInputStream = null;
		try {
			bufferedInputStream = new BufferedInputStream(new FileInputStream(fileName));
			int len = 0;
			//一次读取一个字节 返回值是哪个字节的内容 一次读取一个字节数组 返回的是字节数组的长度
//			while ((len = bufferedInputStream.read()) != -1) {
//				System.out.println((char)len);
//			}
			//一次性读取多个字节
			byte[] tempByte = new byte[1024];
			while ((len = bufferedInputStream.read(tempByte)) != -1) {
				System.out.println(new String(tempByte, 0, len));
			}
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} finally {
			if (bufferedInputStream != null) {
				try {
					bufferedInputStream.close();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}
		
		
	}

字符流(Reader,Writer)

字符流 = 字节流 + 编码表(java提供了相应的转换流)
编码表:由字符及其对应的数值组成的一张表
常见的编码表: ASCII/Unicode字符集、GB2312/GBK/GB18030、UTF-8
字符串可以指定编码表来创建

InputStreamReader

  • InputStreamReader 字符转化流
/*
	 * 使用字符流来一个读取一个字符的方法来读取文件内容
	 */
	public static void readerFile(String fileName) {
		InputStreamReader inputStreamReader  = null;
		try {
			inputStreamReader = new InputStreamReader(new FileInputStream(fileName));
			//一个字符一个字符的读
			int ch = 0;
			while ((ch = inputStreamReader.read()) != -1) {
				System.out.println((char)ch);
			}
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} finally {
			if (inputStreamReader != null) {
				try {
					inputStreamReader.close();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}
	}
	
	/*
	 * 使用字符流 一次读取多个字符 
	 */
	public static void readreFile2(String fileName) {
		InputStreamReader inputStreamReader  = null;
		try {
			inputStreamReader = new InputStreamReader(new FileInputStream(fileName));
			//一次读取多个字符
			char[] ch = new char[1024];//可以自定义长度
			int count = 0;
			while ((count = inputStreamReader.read(ch)) != -1) {
				
				System.out.println(String.valueOf(ch, 0, count));
			}
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} finally {
			if (inputStreamReader != null) {
				try {
					inputStreamReader.close();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}
	}

OutputStreamWriter

  • OutputStreamWriter 字符转换输出流

/*
 * close()和flush()的区别
 * close()关闭流对象,但是先刷新一次缓冲区。关闭流对象之后,流对象不可以在使用了
 * flush()仅仅刷新缓冲区,刷新之后流对象还可以继续使用
 */
/*
	 * 使用字符输出流来写数据
	 */
	public static void writerFile(String fileName) {
		OutputStreamWriter outputStreamWriter = null;
		try {
			//是够在文件后面追加根据创建的字节流, 字符流的构造方法参数都是字节流
			outputStreamWriter = new OutputStreamWriter(new FileOutputStream(fileName));
			//开始写
			for (int i = 0; i < 3; i++) {
				outputStreamWriter.write("我爱你,中国");
			}
			//刷新内容,如果输出流没有关闭,这个时候文件中可能没有刷新我们写入的内容,所以需要刷新内容下
			//当写的操作完成之后再刷新缓存
			outputStreamWriter.flush(); 
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			
		}finally {
			if (outputStreamWriter != null) {
				try {
					outputStreamWriter.close();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}
	}

FileWriter

  • FileWriter: InputStreamReader的子类,由于我们常见的操作都是使用本地默认编码,所以,不用指定编码。 而转换的名称有点长,所以,Java就提供了其子类供我们使用。
/*
	 * 使用fileWriter来写入文件
	 */
	public static void writerFile(String fileName) {
		FileWriter fileWriter = null;
		try {
			fileWriter = new FileWriter(fileName);
			fileWriter.write("我爱你,中国");
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} finally {
			if (fileWriter != null) {
				try {
					fileWriter.close();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}
	}

FileReader

  • FileReader
/*
	 * 使用fileReader一次读取一个字符
	 */
	public static void readerFile(String fileName) {
		FileReader fileReader = null;
		try {
			fileReader = new FileReader(fileName);
			int count = 0;
			while ((count = fileReader.read()) != -1) {
				System.out.println((char)count);
			}
		} catch (IOException e) {
			// TODO: handle exception
		} finally {
			if (fileReader != null) {
				try {
					fileReader.close();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}
	}
	
	/*
	 * 使用fileReader一次读取一个字符数组
	 */
	public static void readerFile2(String fileName) {
		FileReader fileReader = null;
		try {
			fileReader = new FileReader(fileName);
			char[] ch = new char[1024];
			int count = 0;
			while ((count = fileReader.read(ch)) != -1) {
				System.out.println(String.valueOf(ch, 0, count));
			}
		} catch (IOException e) {
			// TODO: handle exception
		} finally {
			if (fileReader != null) {
				try {
					fileReader.close();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}
	}

BufferedWriter

  • BufferedWriter: 字符缓冲输出流
/*
	 * 使用高效输出字符流来写一个字符串到文件总
	 */
	public static void bufferedWriterFile(String fileName) {
		BufferedWriter bufferedWriter = null;
		
		try {
			bufferedWriter = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(fileName)));
			//使用高效字符流来写字符串 到文件
			for (int i = 0; i < 10; i++) {
				bufferedWriter.write("安东尼刷卡号地块撒谎的萨达到拉萨讲道理撒娇的的撒的撒电视剧阿来得及撒来得及");
				//根据系统属性写入一个换行符
				bufferedWriter.newLine();
				//刷新缓冲区
				//bufferedWriter.flush();
			}
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} finally {
			if (bufferedWriter != null) {
				try {
					bufferedWriter.close();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}
	}

BufferedReader

  • BufferedReader 字符缓冲输入流

/*
	 * 字符缓冲流来一次读取一行数据
	 * readLine():读一行文字。 一行被视为由换行符('\ n'),回车符('\ r')中的任何一个或随后的换行符终止。
	 * 包含行的内容的字符串,不包括任何行终止字符,如果已达到流的末尾,则为null
	 */
	public static void readerLineFile(String fileName) {
		BufferedReader bufferedReader = null;

		try {
			bufferedReader = new BufferedReader(new InputStreamReader(new FileInputStream(fileName)));
			// 一次读取一行数据
			String conteString = null;
			while ((conteString = bufferedReader.readLine()) != null) {
				System.out.println(conteString);
			}
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} finally {
			if (bufferedReader != null) {
				try {
					bufferedReader.close();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}
	}
	
/*
	 * 高效字符输入流 一次读取一个字符
	 */
	public static void readerFile(String fileName) {
		BufferedReader bufferedReader = null;
		
		try {
			bufferedReader = new BufferedReader(new InputStreamReader(new FileInputStream(fileName)));
			//高效输入字符流一次读取一个字符
			int ch = 0;
			while ((ch = bufferedReader.read()) != -1) {
				System.out.println((char)ch);
			}
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}finally {
			if (bufferedReader != null) {
				try {
					bufferedReader.close();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}
	}
	
	/*
	 * 高效输入字符流 一次读取一个字符数组
	 *
	 */
	public static void readerFile2(String fileName) {
		BufferedReader bufferedReader = null;
		
		try {
			bufferedReader = new BufferedReader(new InputStreamReader(new FileInputStream(fileName)));
			//高效输入字符流一次读取一个字符
			char[] ch = new char[1024];
			int count = 0;
			while ((count = bufferedReader.read(ch)) != -1) {
				System.out.println(String.valueOf(ch, 0, count));
			}
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}finally {
			if (bufferedReader != null) {
				try {
					bufferedReader.close();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}
	}

操作基本数据类型的流

DataOutputStream

DataOutputStream(数据输出流) :允许把数据和其类型一并写出去。
在这里插入图片描述

public static void write(String fileName) {
		DataOutputStream dataOutputStream = null;
		try {
			dataOutputStream = new DataOutputStream(new FileOutputStream(fileName));
			dataOutputStream.writeFloat(2.11F);
			dataOutputStream.writeInt(100);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}finally {
			if (dataOutputStream != null) {
				try {
					dataOutputStream.close();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}
		
	}

DataInputStream

DataInputStream(数据输入流):用于读取数据输出流写出去的数据
在这里插入图片描述

public static void read(String fileName) {
		DataInputStream dataInputStream = null;
		try {
			dataInputStream = new DataInputStream(new FileInputStream(fileName));
			System.out.println(dataInputStream.readFloat());
			System.out.println(dataInputStream.readInt());
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}finally {
			if (dataInputStream != null) {
				try {
					dataInputStream.close();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}
	}

内存操作流

内存操作流一般用于处理临时信息,因为临时信息不需要保存,使用之后就可以删除。

  • 操作字节数据: ByteArrayInputStream 和 ByteArrayOutputStream
  • 操作字符数组: CharArrayReader 和 CharArrayWriter
  • 操作字符串: StringReader 和 StringWriter
//使用内存操作写数据,其底层是把数据存放在一个byte数组中
		ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
		try {
			byteArrayOutputStream.write("helloworld Java".getBytes());
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		//byteArrayOutputStream.close() 查看源码里面什么也没做,所以根本不需要
		//读取数据
		byte[] cachesByte = byteArrayOutputStream.toByteArray();
		
		ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(cachesByte);
		//一次读一个字节
//		int temp = 0;
//		while ((temp = byteArrayInputStream.read()) != -1) {
//			System.out.println((char)temp);
//		}
		
		/*
		 * 一次读取一个字符数组
		 */
		int temp = 0;
		byte[] tempByte = new byte[1024];
		try {
			while ((temp = byteArrayInputStream.read(tempByte)) != -1) {
				System.out.println(new String(tempByte, 0, temp));
			}
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

打印流

PrintStream/PrintWriter(打印流)

  • 作用:打印流可以实现更方便、更高效的打印数据出去,能实现打印啥出去就是啥出去

  • 打印流的特点:

    • 只有写数据,没有读数据。只能操作目的地,不能操作数据源。
    • 可以操作任意类型的数据
    • 如果启动自动刷新,能够自动刷新
    • 该流是可以直接操作文本文件的。
    • 于其他的流不同的是不会输出IOExpetion
    • 特有的方法,print()、println() 可以输出任意类型的值,前者不换行,后者换行
  • 那些流可以直接操作文本文件?

    • FileInputStream
    • FileOutputStream
    • FileReader
    • FileWriter
    • PrintStream
    • PrintWriter
    • 基本流: 就是能够直接操作读写文件的
    • 高级流: 在基本的基础上提供一些其他的功能

PrintStream

在这里插入图片描述
在这里插入图片描述

PrinWriter

在这里插入图片描述

注意:如果想要实现追加数据的操作, 那么需要包装一个低级流对象。 高级流是不支持的。

PrintStream和PrintWriter的区别

  • 打印数据的功能上是一模一样的:都是使用方便,性能高效(核心优势)
  • PrintStream继承自字节输出流OutputStream,因此支持写字节数据的方法。
  • PrintWriter继承自字符输出流Writer,因此支持写字符数据出去。

打印流的应用-输出语句的重定向

在这里插入图片描述

在这里插入图片描述

序列化和反序列化

把对象以流的方式写入文件保存,成为对象的序列化; 对象中包含的不仅仅是字符,所以需要使用字节流。
**重点: 只有支持java.io.Serializable接口的对象才能写入流中。**只有当类实现这个协议(相当于给这个类加上标记),才可以被序列化和反序列化,如果类没有标记,就会抛出

/*
 * 代表对象实现了序列化 可以被流来操作写入文件和读取,只有实现了Serializable的类才可以被序列化
 */

public class Person implements Serializable {

	/**
	 * 序列化ID:放置序列化和反序列化的时候,由于序列化ID 不同产生的异常,为了保证不管类怎么修改,序列化的ID都不会改变
	 */
	private static final long serialVersionUID = 1L;
	
	
	private String name;
	private int age;
	
	public Person(String name, int age) {
		super();
		this.name = name;
		this.age = age;
	}

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

	@Override
	public String toString() {
		return "Person [name=" + name + ", age=" + age + "]";
	}
}

ObjectOutputStream

  • ObjectOutputStream: 对象序列化流(输出流),把Java对象存入到文件中

在这里插入图片描述

/*
	 * 写一个对象到文件
	 */
	public static void writeObject(Person person, String fileName) {
		ObjectOutputStream objcObjectOutputStream = null;
		try {
			objcObjectOutputStream =  new ObjectOutputStream(new FileOutputStream(fileName));
			objcObjectOutputStream.writeObject(person);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} finally {
			if (objcObjectOutputStream != null) {
				try {
					objcObjectOutputStream.close();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}
		
	}

ObjectInputStream

  • ObjectInputStream: 对象的反序列化流(输入流),把存储在文件中的Java对象读入到内存中来。
    在这里插入图片描述
/*
	 * 读取一个文件
	 */
	public static Object readerObject(String fileName) {
		ObjectInputStream objectInputStream = null;
		Object object = null;
		try {
			objectInputStream =  new ObjectInputStream(new FileInputStream(fileName));
			/*
			 *  readObject(): 方法出了抛出IOException异常外
			 *  还抛出了ClassNotFoundException(class文件对象找不到异常)
			 *  当写入的对象class文件不存在时,抛出此异常,此异常不属于IOException异常
			 */
			object =  objectInputStream.readObject();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (ClassNotFoundException e) {
			// TODO: handle exception
			e.printStackTrace();
		} finally {
			if (objectInputStream != null) {
				try {
					objectInputStream.close();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}
		
		return object;
	}

//输出结果Person [name=zhanshan, age=33]
  • 序列化运行时将每个可序列化的类与称为serialVersionUID的版本号相关联,该序列号在反序列化期间用于验证序列化对象的发送者和接收者是否已加载与该序列化兼容的对象的类。 如果接收方加载了一个具有不同于相应发件人类的serialVersionUID的对象的类,则反序列化将导致InvalidClassException 。 一个可序列化的类可以通过声明一个名为"serialVersionUID"的字段来显式地声明它自己的serialVersionUID,该字段必须是静态的,最终的,类型是long :

    ANY-ACCESS-MODIFIER static final long serialVersionUID = 42L;

  • static关键字:静态关键字

    • 静态关键字优先于非静态加载到内存中(静态优先于对象进入到内存中)
    • 被static修饰的成员变量不能被序列化,序列化的都是对象
  • transient关键字:瞬态关键字

    • 修饰的成员变量不能被序列化
    • 以后如果不想要哪个成员变量序列化,可以用此关键字来修饰
  • 序列化的前提

    • 类必须实现Serializable
    • 必须存在类对象的class文件

IO框架

  • 框架的形式: 一般是把类、接口等编译成class形式,在压缩成一个.jar结尾的文件发行出去。

在这里插入图片描述

什么是IO框架?

  • 封装了Java提供的对文件、数据进行操作的代码,对外提供了更简单的方式来对文件进行操作,对数据进行读写等。
  • Commons-io是apache开源基金组织提供的一组有关IO操作的小框架,目的是提高IO流的开发效率。
    在这里插入图片描述

导入commons-io-xxx.jar框架到项目中去

  • 在项目中创建一个文件夹:lib
  • 将commons-io-xxx.jar文件复制到lib文件夹
  • 在jar文件上点右键,选择Add as Libary -> 点击ok
  • 在类中导报使用

特殊文本文件、日志技术

Properties属性文件

属性文件的特点:

  • 都只能是键值对
  • 键不能重复
  • 文件后缀一般是.properties结尾的,但是不是一定就是。
    在这里插入图片描述

Properties

  • 是一个Map集合(键值对集合),但是我们一般不会当集合使用。
  • 核心作用:Properties是用来代表属性文件的,通过Properties可以读写属性文件里的内容
    在这里插入图片描述

使用Properties读取属性文件里的键值对数据
在这里插入图片描述
在这里插入图片描述

使用Properties把键值对数据写出到属性文件里去
在这里插入图片描述
在这里插入图片描述

XML文件

概述

XML(全称EXtensible Markup Language, 可扩展标记语言)

  • 本质上是一种数据的格式,可以用来存储复杂的数据结构,和数据关系。 在这里插入图片描述

XML的特点

  • XML中的"<标签名>"称为一个标签或一个元素,一般是成对出现的。
  • XML中的标签可以自己定义(可扩展),但必须要正确的嵌套。
  • XML中只能有一个跟标签
  • XML中的标签可以有属性
  • 如果一个文件中放置的是XML格式的数据,这个文件就是XML文件,后缀一般要写成.xml。

XML的创建

  • 就是创建一个XML类型的文件,要求文件的后缀必须使用xml,如hello-world.xml
    在这里插入图片描述

XML的语法规则

  • XML文件的后缀名为:xml,文档声明必须是第一行
    在这里插入图片描述
  • XML中可以定义注释信息:<!--注释内容-->
  • XML总书写 ”<“、”&“等,可能会穿线冲突,导致报错,此时可以用如下特殊字符代替。
    在这里插入图片描述
  • XML中可以写一个叫CDATA的数据区:<![CDATA[ ... 内容... ]]>, 里面的内容可以随便写

XMl的作用和应用场景

  • 应用场景:经常用来为系统的配置文件;或作为一种特殊的数据结构,在网络中进行传输。
    在这里插入图片描述

读取XML中的数据

程序员并不需要自己写原始的IO流代码来解析XML,难度大!也相当繁琐!
其实有很多开源的、好用的、解析XML的框架,最知名的是Dom4j(第三方的)

步骤:
在这里插入图片描述
在这里插入图片描述

Dom4j解析XML-得到Document对象

  • SAXReader: Dom4j提供的解析器,可以认为是代表整个Dom4j框架
    在这里插入图片描述

Document
在这里插入图片描述
在这里插入图片描述
解析是自上而下的解析方式

Element提供的方法
在这里插入图片描述
在这里插入图片描述

如何使用程序把数据写入到XML文件中去?

不建议使用Dom4j做, 推荐直接使用程序的数据凭借成XML格式,然后用IO流写出去!
请添加图片描述

约束XML文件的编写

限制XML文件只能按照某种格式进行书写。

相关XML约束内容参考:Java学习-XML基础

日志技术

概述

目前记录日志的方案:
在这里插入图片描述
输出语句的弊端

  • 日志回展示在控制台
  • 不能更方便的将日志记录到其他的位置(文件,数据库)
  • 想取消日志,需要修改源码才可以完成

日志技术

  • 可以将系统执行的信息,方便的记录到指定的位置(控制台、文件中、数据库中)。
  • 可以随时以开关的形式控制日志的启停,无需侵入到源码中去进行修改。

体系

日志技术的体系结构
在这里插入图片描述

  • 日志框架:牛人或者第三方公司已经做好的实现代码,后来者直接可以拿去使用
  • 日志接口:设计日志框架的一套标准,日志框架需要实现这些接口
  • 注意1:因为对Commons Logging接口不满意,有人就搞了SLF4j;因为对Log4j的性能不满意,有人就搞了Logback
  • 注意2Logback是基于slf4j的日志规范实现的框架

Logback日志框架官方网站:Logbakc官网
在这里插入图片描述

Logback快速入门

如何使用Logback日志框架,记录系统的运行信息。

  • 导入Logback框架到项目中去。
    在这里插入图片描述
  • 将Logback框架的核心配置文件logback.html直接拷贝到src目录下(必须是src下
  • 创建Logback框架提供的Logger对象,然后用Logger对象调用其他提供的方法就可以实现系统的日志信息。
    在这里插入图片描述
    请添加图片描述

核心配置文件logback.xml

  • 对Logback日志框架进行控制的

日志的输出位置、输出格式的设置

  • 通常可以设置2个输出日志的位置: 一个是控制台、一个是系统文件中
    在这里插入图片描述

开启日志(ALL),取消日志(OFF)
在这里插入图片描述

logback.xml的一些内容介绍
日志输出到控制台:
在这里插入图片描述

日志输出到文件:
在这里插入图片描述

控制日志的开启和取消: OFF: 取消日志 ALL:开启日志
在这里插入图片描述

Logback设置日志级别

什么是日志级别

  • 日子级别指的是日志信息的类型,日志都会分级别,常见的日志级别如下(优先级依次升高):
    在这里插入图片描述

为什么要学习日志级别?
在这里插入图片描述

  • 只有日志级别是大于或等于核心配置文件配置的日志级别,才会被记录,否则不记录
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值