IO流
节点流和处理流
- 节点流可以从一个特点的数据源读写数据,如FileReader、FileWriter
- 处理流(也叫包装流)是“连接”在已存在的流(节点流或处理流)之上,为程序提供更为强大的读写功能,也更加灵活,如BufferedReader、.BufferedWriter
区别和联系
- 节点流是底层流(低级流),直接和数据源相连接。
- 处理流(包装流)对节点流进行了包装,既可以消除不同节点流的实现差异,也可以提供更方便的方法来完成输入输出。
- 处理流对节点流进行了包装,使用了修饰器的设计模式,不会直接与数据源相连接。
处理流的特点:
-
性能的提高:主要以增加缓冲的方式来提高输入输出的效率
-
操作的便捷:处理流可能提供了一系列便捷的方法来一次输入输出大批量的数据,使用更加灵活方便
处理流 - BufferedReader 和 BufferedWriter
-
BufferedReader和BufferedWriter属于字符流,是按照字符来读取数据的
-
关闭时处理流,只需要关闭外层流即可
![](/i/l/?n=23&i=blog/2387844/202307/2387844-20230723231257089-1227676537.png)
![](/i/l/?n=23&i=blog/2387844/202307/2387844-20230723231317332-383804151.png)
应用案例
1.使用BufferedReader读取文本文件,并显示在控制台
@Test
public void m1() {
// String filePath = "F:\\VSCode\\JAVA\\file\\test\\FileWriter.test";
String filePath = "F:\\VSCode\\JAVA\\file\\test\\the Zen of Python.txt";
BufferedReader bufferedReader = null;
String line;
try {
bufferedReader = new BufferedReader(new FileReader(filePath));
while ((line = bufferedReader.readLine()) != null) {
System.out.println(line);
}
} catch (IOException e) {
e.printStackTrace();
}finally {
if (bufferedReader != null) {
try {
bufferedReader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
应用案例
使用BufferedWriter写入到文件
@Test
public void m2() throws IOException {
String filePath = "F:\\VSCode\\JAVA\\file\\test01\\a.txt";
BufferedWriter writer = new BufferedWriter(new FileWriter(filePath));
writer.write("墨染启明,hello");
writer.newLine();
writer.write("墨染启明,hello");
writer.newLine();
writer.write("墨染启明,hello");
writer.newLine();
writer.close();
}
应用案例
综合使用 BufferedReader 和 BufferedWriter 完成文本文件拷贝
public class Copy01 {
// 1. BufferedReader 和 BufferedWriter 是按照字符操作
//2. 不要去操作 二进制文件[声音, 视频, doc, pdf ], 可能造成文件损坏
public static void main(String[] args) throws IOException {
String src = "F:\\VSCode\\JAVA\\file\\test\\the Zen of Python.txt";
String dest = "F:\\VSCode\\JAVA\\file\\test02\\b.txt";
copy(src, dest);
}
public static void copy(String srcPath, String destPath) throws IOException {
BufferedReader bufferedReader = new BufferedReader(new FileReader(srcPath));
BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter(destPath));
String line;
while ((line = bufferedReader.readLine()) != null) {
bufferedWriter.write(line);
bufferedWriter.newLine();
}
bufferedWriter.close();
bufferedReader.close();
}
}
处理流-BufferedInputStream 和 BufferedOutputStream
![](/i/l/?n=23&i=blog/2387844/202307/2387844-20230723231425041-560280988.png)
![](/i/l/?n=23&i=blog/2387844/202307/2387844-20230723231438716-2040530466.png)
- BufferedInputStream 是字节流,在创建BufferedInputStream时,会创建一个内部缓冲区数组。
- BufferedOutputStream是字节流,实现缓冲的输出流,可以将多个字节写入底层输出流中,而不必对每次字节写入调用底层系统
应用案例
编程完成圈片/音乐的拷贝(要求使用Buffered.流)
public class Copy02 {
public static void main(String[] args) {
String srcPath = "F:\\VSCode\\JAVA\\file\\test\\No One But You.mp3";
String destPath = "F:\\VSCode\\JAVA\\file\\test03\\copy.mp3";
copy02(srcPath, destPath);
}
public static void copy02(String scr, String dest) {
BufferedInputStream bufferedInputStream = null;
BufferedOutputStream bufferedOutputStream = null;
byte[] bytes = new byte[16];
int len;
try {
bufferedInputStream = new BufferedInputStream(new FileInputStream(scr));
bufferedOutputStream = new BufferedOutputStream(new FileOutputStream(dest));
while ((len = bufferedInputStream.read(bytes)) != -1) {
bufferedOutputStream.write(bytes, 0, len);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
bufferedOutputStream.close();
bufferedInputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
对象流-ObjectInputStream 和 ObjectOutputStream
看一个需求
-
将int num=100这个int数据保存到文件中,注意不是100数字,而是int 100,并且,能够从文件中直接恢复int 100
-
将
Dog dog=new Dog(“小黄”,3)
这个dog对像保存到文件中,并且能够从文件恢复. -
上面的要求,就是能够将基本数据类型或者对象进行序列化和反序列化操作
序列化和反序列化
-
序列化就是在保存数据时,保存数据的值和数据类型
-
反序列化就是在恢复数据时,恢复数据的值和数据类型
-
需要让某个对像支持序列化机制,则必须让其类是可序列化的,为了让某个类是可序列化的,该类必须实现如下两个接口之一:
- Serializable/这是一个标记接口,没有方法
- Externalizable该接口有方法需要实现,因此我们一般实现上面的Serializable接口
对象流的介绍
功能:提供了对基本类型或对象类型的序列化和反序列化的方法
ObjectOutputStream:提供序列化功能
ObjectInputStream:提供反序列化功能
![](/i/l/?n=23&i=blog/2387844/202307/2387844-20230723231619845-460928715.png)
![](/i/l/?n=23&i=blog/2387844/202307/2387844-20230723231640850-519600470.png)
注意事项和细节说明
- 读写顺序要一致
- 要求序列化或反序列化对像,需要实现Serializable
- 序列化的类中建议添加SerialVersionUID,为了提高版本的兼容性
- 个序列化对象时,默认将里面所有属性都进行序列化,但除了static或transient修饰的成员
- 序列化对象时,要求里面属性的类型也需要实现序列化接口
- 序列化具备可继承性,也就是如果某类已经实现了序列化,则它的所有子类也已经默认实现了序列化
public class ObjectOutStream01 {
public static void main(String[] args) throws IOException {
// 序列化后,保存的文件格式,不是存文本,而是按照他的格式来保存
String filePath = "F:\\VSCode\\JAVA\\file\\test03\\data.dat";
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(filePath));
// 序列化数据到 e:\\data.dat
oos.writeInt(100); // int-->Integer(实现了serializable接口)
oos.writeBoolean(true); // boolean --> Boolean(实现了serializable接口)
oos.writeChar('a'); // char -- > Character (实现了serializable接口)
oos.writeDouble(3.14); // double --> Double (实现了serializable接口)
oos.writeUTF("墨染启明"); // String(实现了serializable接口)
// 保存一个Dog 对象
oos.writeObject(new Dog(3, "wangcai", "yello", "Japan"));
oos.close();
System.out.println("数据保存完毕(序列化形式)");
}
}
// 如果需要序列化某个类的对象,实现Serializable接口
class Dog implements Serializable {
private int age;
private String name;
//serialVersionUID 序列化的版本号,可以兼容性
private static final long serialVersionUID = 1L;
private transient String color;
private static String nation;
private Master master = new Master();
public Dog(int age, String name, String color, String nation) {
this.age = age;
this.name = name;
this.color = color;
this.nation = nation;
}
@Override
public String toString() {
return "Dog{" +
"age=" + age +
", name='" + name + '\'' +
", color='" + color + '\'' +
", nation='" + nation + '\'' +
", master='" + master + '\'' +
'}';
}
}
class Master implements Serializable{} // 属性需要序列化
public class ObjectInputSteam01 {
public static void main(String[] args) throws Exception{
String filePath = "F:\\VSCode\\JAVA\\file\\test03\\data.dat";
ObjectInputStream ois = new ObjectInputStream(new FileInputStream(filePath));
// 读取
// 1.读取(反序列化)的顺序需要和保存数据(序列化)的顺序一致
System.out.println(ois.readInt());
System.out.println(ois.readBoolean());
System.out.println(ois.readChar());
System.out.println(ois.readDouble());
System.out.println(ois.readUTF());
Object o = ois.readObject();
System.out.println(o.getClass());
System.out.println("dog= " + o); // 底层 Object -- Dog
ois.close();
}
}
标准输入输出流
类型 | 默认设备 | |
---|---|---|
System.in 标准输入 | InjputStream | 键盘 |
System.out 标准输出 | PrintStream | 显示器 |
public static void main(String[] args) {
// 标准输入 键盘
// System类 的public final static InputStream in = null
// System.in 编译类型:InputStream
// System.in 运行类型:BufferedInputStream
System.out.println(System.in.getClass()); // class java.io.BufferedInputStream
// 标准输出 显示器
// System.out public final static PrintStream out = null;
// System.out 编译类型:PrintStream
// System.out 运行类型:PrintStream
System.out.println(System.out.getClass()); //class java.io.PrintStream
System.out.println("hello");
Scanner scanner = new Scanner(System.in);
System.out.println("输入内容");
String next = scanner.next();
System.out.println(next);
}
转换流 InputStreamReader 和 OutputStreamWriter
![](/i/l/?n=23&i=blog/2387844/202307/2387844-20230723231726580-280339496.png)
![](/i/l/?n=23&i=blog/2387844/202307/2387844-20230723231740973-936419188.png)
- InputStreamReader:Readert的子类,可以将InputStream(字节流)包装成(转换)Reader(字符流)
- OutputStreamWriter:Writert的子类,实现将OutputStream(字节流)包装成Writer(字符流)
- 当处理纯文本数据时,如果使用字符流效率更高,并且可以有效解决中文问题,所以建议将字节流转换成字符流
- 可以在使用时指定编码格式(比如utf-8,gbk,gb2312,1S08859-1等)
应用案例
需程将字节流Filelnputstream包装成转换成字符流InputStreamReader,对文件进行读取(按照utf-8/gbk格式),进而在包装成BufferedReader
public class InputStreamReader01 {
public static void main(String[] args) throws Exception {
String filePath = "F:\\VSCode\\JAVA\\file\\test03\\a.txt";
// 1.new FileInputStream(filePath) -->转成 InputStreamReader
// InputStreamReader isr = new InputStreamReader(new FileInputStream(filePath), "gbk");
// InputStreamReader isr = new InputStreamReader(new FileInputStream(filePath), "utf-8"); // 乱码
// 2.指定编码为 gbk
// 3. 把 InputStreamReader 传入 BufferedReader
// BufferedReader br = new BufferedReader(isr);
BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(filePath), "gbk"));
String s = br.readLine();
System.out.println(s);
br.close();
}
}
public class OutputStreamWriter01 {
public static void main(String[] args) throws IOException {
String filePath = "F:\\VSCode\\JAVA\\file\\test02\\b.txt";
// BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(filePath), "gbk"));
// 默认 utf-8
BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(filePath), StandardCharsets.UTF_16));
bufferedWriter.write("墨染启明");
bufferedWriter.close();
}
}
打印流 PrintStream 和 PrintWriter
![](/i/l/?n=23&i=blog/2387844/202307/2387844-20230723231833430-470566909.png)
![](/i/l/?n=23&i=blog/2387844/202307/2387844-20230723231848119-1230598950.png)
打印流只有输出流,没有输入流
public class PrintWriter01 {
public static void main(String[] args) throws FileNotFoundException {
PrintWriter printWriter = new PrintWriter(System.out);
// PrintWriter printWriter = new PrintWriter("F:\\VSCode\\JAVA\\file\\test03\\c.txt");
printWriter.print("hi, 北京你好");
printWriter.close(); // flush + 关闭流
}
}
public class PrintStream01 {
public static void main(String[] args) throws IOException {
PrintStream out = System.out;
// 默认情况下,PrintStream 输出数据的位置 是 标准输出,即显示器
out.println("jack");
/*
public void print(String s) {
if (s == null) {
s = "null";
}
write(s);
}
*
*
* */
out.write("hello".getBytes());
System.out.write("xxxx".getBytes(StandardCharsets.UTF_8));
out.close();
// 可以修改打印流的输出位置
System.setOut(new PrintStream("F:\\VSCode\\JAVA\\file\\test03\\print.txt"));
System.out.println("sunday"); // 输出到该文件
// System.setOut();
System.out.println("Monday");
}
}
Properties 类
如下一个配置文件mysql.properties
ip=192.168.0.13
user=root
pwd=12345
请问编程读取ip、user和pwd的值是多少
分析
1.传统的方法
2.使用Properties类可以方便实现
public class Properties01 {
public static void main(String[] args) throws IOException {
String filePath = "F:\\VSCode\\JAVA\\file\\test03\\mysql.properties";
BufferedReader bufferedReader = new BufferedReader(new FileReader(filePath));
String line;
while ((line = bufferedReader.readLine()) != null) {
String[] split = line.split("=");
// 如果要求拿到ip
if ("ip".equals(split[0])) {
System.out.println(split[0] + " 的值是:" + split[1]);
}
}
bufferedReader.close();
}
}
基本介绍
-
专门用于读写配置文件的集合类
-
配置文件的格式:
键=值
键=值
-
注意:键值对不需要有空格,值不需要用引号一起来。默认类型是String
Properties的常见方法
-
Ioad:加载配置文件的键值对到Propertiesi对象
-
list:将数据显示到指定设备
-
getProperty(key):根据键获取值
-
setProperty(key,value):设置键值对到Properties对象
-
store:将Propertiest中的键值对存储到配置文件,在idea中,保存信息到配置文件,如果含有中文,会存储为unicode码
String getProperty(String key)
Searches for the property with the specified key in this property list.
String getProperty(String key, String defaultValue)
Searches for the property with the specified key in this property list.
void list(PrintStream out)
Prints this property list out to the specified output stream.
void list(PrintWriter out)
Prints this property list out to the specified output stream.
void load(InputStream inStream)
Reads a property list (key and element pairs) from the input byte stream.
void load(Reader reader)
Reads a property list (key and element pairs) from the input character stream in a simple line-oriented format.
void save(OutputStream out, String comments)
Deprecated.
This method does not throw an IOException if an I/O error occurs while saving the property list. The preferred way to save a properties list is via the store(OutputStream out, String comments) method or the storeToXML(OutputStream os, String comment) method.
Object setProperty(String key, String value)
Calls the Hashtable method put.
void store(OutputStream out, String comments)
Writes this property list (key and element pairs) in this Properties table to the output stream in a format suitable for loading into a Properties table using the load(InputStream) method.
void store(Writer writer, String comments)
Writes this property list (key and element pairs) in this Properties table to the output character stream in a format suitable for using the load(Reader) method.
public static void main(String[] args) throws IOException {
// 使用Properties 类来读取
// 1.创建Properties 对象
Properties properties = new Properties();
// 2. 加载指定的配置文件
properties.load(new FileReader("F:\\VSCode\\JAVA\\file\\test03\\mysql.properties"));
// 3. 把k-v显示在控制台
properties.list(System.out);
// 4. 根据key 获取对应的值
String user = properties.getProperty("user");
String pwd = properties.getProperty("pwd");
System.out.println(user + " 的密码: " + pwd);
}
public static void main(String[] args) throws IOException {
// 使用Properties 类来创建配置文件,修改配置文件内容
Properties properties = new Properties();
// 创建
properties.setProperty("charset", "utf-8");
properties.setProperty("user", "杰克"); // 中文的unicode码
properties.setProperty("pwd", "abc111");
properties.setProperty("pwd", "123abc");
// 将k-v保存到文件中即可
properties.store(new FileOutputStream("F:\\VSCode\\JAVA\\file\\test03\\mysql01.properties" ),"hello这是注释");
System.out.println("保存配置文件成功");
}
标签:Java,复习,System,String,IO,new,序列化,public,out
From: https://www.cnblogs.com/ai135/p/17576181.html