三、节点流和处理流
基本介绍:
- 节点流和处理流
3.1、处理流BufferedReader和BufferedWriter
- BufferedReader和BufferedWriter属于字符流,是按照字符来读取数据的关闭时,只需要关闭外层
BufferedReader代码演示:
import org.junit.jupiter.api.Test;
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
/**
* @author java小豪
* @version 1.0.0
* @date 2022/11/16
* @description 处理流
*/
public class BufferedReader_ {
public static void main(String[] args) {
}
@Test
public void read() throws Exception {
String filePath = "F:\\file\\story.txt";
// 创建BufferedReader对象
BufferedReader bufferedReader = new BufferedReader(new FileReader(filePath));
// 读取
String line;
// 说明
// 1.bufferedReader.readLine() 是按行读取文件
// 2.当返回null 时,表示文件读取完毕
while ((line = bufferedReader.readLine()) != null) {
System.out.print(line);
}
// 关闭流 只需要关闭 BufferedReader, 因为底层会自动关闭 节点流
bufferedReader.close();
}
}
BufferedWriter代码演示:不能处理二进制文件[pdf/word/声音/图片等]
import org.junit.jupiter.api.Test;
import java.io.*;
/**
* @author java小豪
* @version 1.0.0
* @date 2022/11/16
* @description 文件拷贝
*/
public class BufferedCopy_ {
public static void main(String[] args) {
}
@Test
public void test() {
String filePath = "F:\\file\\ok.txt";
String destFilePath = "F:\\file\\ok1.txt";
BufferedReader bufferedReader = null;
BufferedWriter bufferedWriter = null;
String line;
try {
bufferedReader = new BufferedReader(new FileReader(filePath));
bufferedWriter = new BufferedWriter(new FileWriter(destFilePath));
// readLine() 读取一行内容,但是没有换行
while ((line = bufferedReader.readLine()) != null) {
// 每读取一行就写进去
bufferedWriter.write(line);
// 插入一个换行
bufferedWriter.newLine();
}
System.out.println("拷贝完毕....");
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (bufferedReader != null) {
// 关闭流
bufferedReader.close();
}
if (bufferedWriter != null) {
// 关闭流
bufferedWriter.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
3.2、处理流BufferedInputStream和BufferedOutputStream
- 使用BufferedInputStream和BufferedOutputStream可以完成二进制文件的拷贝
import org.junit.jupiter.api.Test;
import java.io.*;
/**
* @author java小豪
* @version 1.0.0
* @date 2022/11/16
* @description 文件拷贝
*/
public class BufferedCopy1 {
public static void main(String[] args) {
}
@Test
public void copy() {
String srcPath = "F:\\file\\1.jpg";
String destPath = "F:\\file\\2.jpg";
// 创建BufferedInputStream和BufferedOutputStream
BufferedInputStream bis = null;
BufferedOutputStream bos = null;
try {
bis = new BufferedInputStream(new FileInputStream(srcPath));
bos = new BufferedOutputStream(new FileOutputStream(destPath));
// 循环读取文件,并写入到 destPath
byte[] bytes = new byte[1024];
int readLine = 0;
// 当返回 -1 时表示读取完毕
while((readLine = bis.read(bytes)) != -1) {
bos.write(bytes, 0, readLine);
}
System.out.println("文件拷贝完毕....");
} catch (IOException e) {
e.printStackTrace();
} finally {
// 关闭流,关闭外层的处理流
try {
if (bis != null) {
bis.close();
}
if (bos != null) {
bos.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
3.3、对象流ObjectInputStream和ObjectOutputStream
- 序列化和反序列化
- 序列化就是在保存数据时,保存==数据的值==和==数据类型==
- 反序列化就是在恢复数据时,恢复==数据的值==和==数据类型==
- 需要让某个对象支持序列化,必须让其类是可序列化的,必须实现如下两个接口之一:Serializable(标记接口)和Externalizable
ObjectInputStream和ObjectOutputStream的类图:
使用ObjectOutputStream 序列化基本数据类行和一个Dog对象(name, age)并保存到data.dat文件里面
import java.io.*;
/**
* @author java小豪
* @version 1.0.0
* @date 2022/11/16
* @description ObjectOutputStream的使用
*/
public class ObjectOutputStream_ {
public static void main(String[] args) throws IOException {
// 序列化后保存的文件格式,不是纯文本,而是按照它的格式保存的
String filePath = "F:\\file\\data.dat";
ObjectOutputStream os = new ObjectOutputStream(new FileOutputStream(filePath));
// 序列化数据
os.write(100);
// 自动装箱boolean ----> Boolean (实现了 Serializable)
os.writeBoolean(true);
// 自动装箱char ----> Character (实现了 Serializable)
os.writeChar('a');
os.writeUTF("java小豪");
// 保存一个Dog对象
os.writeObject(new Dog("旺财", 3));
os.close();
System.out.println("数据保存完毕(序列化形式)");
}
}
// 如果需要序列化某个类的对象,实现Serializable
class Dog implements Serializable {
private String name;
private int age;
public Dog(String name, int age) {
this.name = name;
this.age = age;
}
}
注意事项
- 读写顺序要一致
- 要求实现序列化或反序列化对象实现Serializable
- 序列化对象时,默认将里面的所有属性都进行序列化,除了static或transient修饰的成员
- 序列化对象时,要求里面的属性的类型也需要实现序列化接口
- 序列化具备可继承性,也就是某类实现了序列化,他的所有子类也已经默认实现了序列化
3.4、标准输入输出流
- System.in和System.out
/**
* @author java小豪
* @version 1.0.0
* @date 2022/11/16
* @description 标准输入和输出流
*/
public class InputAndOutput {
public static void main(String[] args) {
//System类里面的一个属性 public final static InputStream in = null;
// 编译类型 为 InputStream 运行类型 BufferedInputStream
System.out.println(System.in.getClass());
// System.out 是 public final static PrintStream out = null;
// 编译类型 为 PrintStream 运行类型 为PrintStream 标准输出(显示器)
System.out.println(System.out.getClass());
}
}
3.5、转换流InputStreamReader和OutputStreamWriter
- InputStreamReader: Reader的子类,可以将InputStream(字节流)包装成(转换)Reader(字符流)
- OutputStreamWriter: Writer的子类,可以实现将OutputStream(字节流)包装成Writer(字符流)
- 当处理纯文本数据时,如果使用字符流效率更高,并且可以有效解决中文问题,所以建议将字节流转换成字符流
- 可以在使用时指定编码格式(比如 utf-8, gbk, gb2312, ISO8855-1等)
InputStreamReader的类图:
OutputStream的类图:
示例1:字节流FileInputStream包装成(转换成)字符流InputStreamReader,对文件进行读取(按照UTF-8/GBK格式)进而包装成BufferedReader
import java.io.*;
/**
* @author java小豪
* @version 1.0.0
* @date 2022/11/28
* @description 使用InputStreamReader解决中文乱码问题
* <p>
* 将字节流 FileInputStream 转换成 InputStreamReader, 指定编码gbk/utf-8
* </p>
*/
public class InputStreamReader_ {
public static void main(String[] args) throws IOException {
String filePath = "F:\\file\\a.txt";
// 1. new FileInputStream 转成 InputStreamReader 指定编码为GBK
InputStreamReader isr = new InputStreamReader(new FileInputStream(filePath), "GBK");
// 2. 把 InputStreamReader 传入 BufferedReader
BufferedReader br = new BufferedReader(isr);
// 将 2 和 3 和在一起
// BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(filePath), "GBK"));
// 3. 读取
String s = br.readLine();
System.out.println("读取文件的内容为:" + s);
// 4. 关闭外层流
br.close();
}
}
示例2:将字节流FileOutputStream包装成(转换成)字符流OutputStreamWriter,对文件进行写入(按照GBK格式,可以指定其他:UTF-8)
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
/**
* @author java小豪
* @version 1.0.0
* @date 2022/11/28
* @description 使用OutputStreamWriter将FileOutputStream字节流,转换成字符流 OutputStreamWriter
*/
public class OutputStreamWriter_ {
public static void main(String[] args) throws IOException {
String filePath = "F:\\file\\a.txt";
String charSet = "UTF-8";
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream(filePath), charSet);
osw.write("hi, 孙悟空");
osw.close();
System.out.println("按照 " + charSet + "保存文件成功~");
}
}
3.6、打印流PrintStream 和 PrintWriter
注意:打印流只有输出流,没有输入流
PrintStream的类图
PrintWriter的类图
PrintStream示例:
import java.io.IOException;
import java.io.PrintStream;
/**
* @author java小豪
* @version 1.0.0
* @date 2022/11/28
* @description 演示PrintStream(字节打印流)、
*/
public class PrintStream_ {
public static void main(String[] args) throws IOException {
PrintStream ps = System.out;
// 默认情况下,PrintStream 输出数据的位置是标准输出
/*
public void print(String s) {
if (s == null) {
s = "null";
}
write(s);
}
*/
ps.println("john Hello");
// 因为print底层使用write,所以我们可以调用write进行打印/输出
ps.write("孙悟空,你好".getBytes());
ps.close();
//我们可以修改打印输出流的位置,修改成到 "F:\\file\\f1.txt"
System.setOut(new PrintStream("F:\\file\\f1.txt"));
System.out.println("hello, 孙悟空");
}
}
PrintWriter示例:
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
/**
* @author java小豪
* @version 1.0.0
* @date 2022/11/28
* @description 演示PrintWriter的使用
*/
public class PrintWriter_ {
public static void main(String[] args) throws IOException {
// PrintWriter pw = new PrintWriter(System.out);
PrintWriter pw = new PrintWriter(new FileWriter("F:\\file\\f2.txt"));
pw.print("hello, 北京~");
pw.close();
}
}
四、Properties类
properties类可以轻松的处理*.properties文件
Properties类常见方法:
- load:加载配置文件的键值对到Properties对象
- list:将数据显示到指定位置
- getProperty(key):根据键获取值
- setProperty(key, value):设置键值对到Properties对象
- store:将Properties中的键值对存储到配置文件,在idea中保存文件如果有中文,会存储为Unicode码
示例1:读取mysql.properties文件,并得到ip,user 和 pwd
- 传统方法
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
/**
* @author java小豪
* @version 1.0.0
* @date 2022/11/28
* @description 演示Properties类的使用
*/
public class Properties01 {
public static void main(String[] args) throws IOException {
// 读取mysql.properties文件并得到ip、user和pwd
BufferedReader br = new BufferedReader(new FileReader("src\\mysql.properties"));
String line = "";
while((line = br.readLine()) != null ) {
String[] split = line.split("=");
System.out.println(split[0] + "值是:" + split[1]);
}
br.close();
}
}
- 使用Properties类进行读取
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.Properties;
/**
* @author java小豪
* @version 1.0.0
* @date 2022/11/28
* @description
*/
public class Properties02 {
public static void main(String[] args) throws IOException {
// 使用Properties 类来读取mysql.properties 文件
// 1.创建Properties 对象
Properties properties = new Properties();
// 2.加载指定的配置文件
properties.load(new FileReader("src/mysql.properties"));
// 3.把k-v显示到控制台
properties.list(System.out);
// 4.根据键获取对应的值
String user = properties.getProperty("username");
String pwd = properties.getProperty("password");
System.out.println("用户名=" + user);
System.out.println("密码=" + pwd);
}
}
- 使用Properties修改配置文件
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Properties;
/**
* @author java小豪
* @version 1.0.0
* @date 2022/11/29
* @description
*/
public class Properties03 {
public static void main(String[] args) throws IOException {
// 使用Properties 类来创建 配置文件,修改配置文件内容
Properties properties = new Properties();
// 创建
// 1.如果该文件没有key,就是创建
// 2.如果该文件有key,就是修改
properties.setProperty("charset", "utf-8");
properties.setProperty("user", "孙悟空");
properties.setProperty("pwd", "888888");
// 将k-v 存储在文件中
properties.store(new FileOutputStream("src\\mysql2.properties"), null);
System.out.println("保存文件成功");
}
}