节点流处理流
节点流和包装流是对流的另外一种分类 , 节点流可以从一个特定的数据源读写数据 , 包装流是连接已经存在的节点流或者处理流之上 , 提供更强大的读写功能
节点流处理流一览
节点流
节点流是对各种资源的直接操作 , 属于比较低级的操作

包装流
包装流在节点流之上提供更强大的功能 , 可以用包装流对应的节点流构造包装流 , 如
bufferedReader 可以接受 Reader 的子类 来构造
包装流中封装了read write 等节点流的基类 , 使其可以灵活地接受各种节点流 , 对访问的资源不会有限制 , 可以消除各个节点流之间的差异 , 有的流对文件操作 , 有的流对数组操作 , 你想对那种数据源操作 ,你就传入那种节点流 , 包装起来之后可以 更加方便的输入输出

字符装流
流的输入
以 bufferedReader 为例子
方法 | 解释 |
---|---|
bufferedReader.readLine() | 返回String,读完返回null,不读回车换行 |
流的输出
以 bufferedWriter 为例子
bufferedWriter.write(12); | int 为ACS , 读取的时候需要强转 , 建议直接输入时候转为String |
bufferedWriter.newLine(); | 包装流写入没有换行,newline函数可以根据系统的不同写入不同的换行符 |
bufferedWriter.write("akaashi"); | String / char[ ] |
bufferedWriter.write("akaashi",0,1); | tring/char[],开始下标,截取长度 |
package Io_;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.FileWriter;
public class _01 {
public static void main(String[] args) throws Exception{
String path = "d://aa.txt";
BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter(path, false));
bufferedWriter.write("12345678654",0,9);
bufferedWriter.close();
BufferedReader bufferedReader = new BufferedReader(new FileReader(path));
String aa ;
while ((aa = bufferedReader.readLine()) != null) {
System.out.print(aa);
}
bufferedReader.close();
//必须要关闭或者刷新,不然写不进去
}
}
文件拷贝
package Io_;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.FileWriter;
/**
* @author Akaashi
* @version 1.0
*/
public class _02 {
public static void main(String[] args) throws Exception{
String a1 = "d://a1.txt";
String a2 = "d://a2.txt";
BufferedReader bufferedReader = new BufferedReader(new FileReader(a1));
BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter(a2,true));
String num ;
while ((num = bufferedReader.readLine())!=null){
bufferedWriter.write(num);
bufferedWriter.newLine();
}
bufferedReader.close();
bufferedWriter.close();
}
}
字节包装流
用于处理二进制的数据源 , 直接传入字节处理流即可
流的输入
方法 | 解释 |
---|---|
read ( ) | 读一个 , 数据存在 int中 , 读完返回-1 , |
read ( byte [] , int off , int len ) | 读一个数组 , |
流的输出
方法 | 解释 |
---|---|
flush ( ) | 刷新,要刷新才算写入 |
write ( ) | 写一个 |
write ( byte [] , int off , int len ) | 写一个数组 |
对象包装流
保存的是序列化的文本 , 就是不仅仅保存内容 , 也保存数据类型
序列化
只有实现了可序列化接口的内容才能使用对象流 , 特别是自己定义的对象 , 要继承可序列化接口 , 可以下面两个接口选一个
-
Serializable
标记接口 , 没有方法 , 直接实现就行 , 建议选这个
-
Externalizable
其中有两个方法需要去实现
最基本的包装类都实现了可序列化功能
- 可序列化的类中要保证每一个属性都是序列化的
- 序列化具有可继承性,父类可序列化,子类也可以
流的输入
提供反序列化功能 , 为使用修饰器模式的包装流
序列化之后 , 保存的文件格式不是 txt 是 dat
方法 | 解释 |
---|---|
writeInt | 保存数字 |
writeChar | 保存字符 |
writeUTF | 保存字符串 |
writeObject | 保存对象 |
单独写write ( ) 无法保存数据类型
public class _03 {
public static void main(String[] args) throws Exception{
ObjectOutputStream objOutput = new ObjectOutputStream(new FileOutputStream("D://data.dat",true));
objOutput.writeInt(100);
objOutput.writeChar('a');
objOutput.writeUTF("字符串");
objOutput.writeObject(new People("赤苇",24));
objOutput.close();//不关闭流会导致写入错误
}
}
class People implements Serializable{
String name;
int age;
public People(String name, int age) {
this.name = name;
this.age = age;
}
@Override//在加入,删除了toString,或者更新了对象的方法的时候需要将对象重新保存才能正确读取 , 修改toString方法不用重新写入也可以修改
public String toString() {
return "People{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
流的输出
提供序列化功能 , 为使用修饰器模式的包装流
需要保存顺序和读取顺序一致
package Io_;
import java.io.FileInputStream;
import java.io.ObjectInputStream;
/**
* @author Akaashi
* @version 1.0
*/
public class _04 {
public static void main(String[] args) throws Exception{
ObjectInputStream objInput = new ObjectInputStream(new FileInputStream("D://data.dat"));
System.out.println(objInput.readInt());
System.out.println(objInput.readChar());
System.out.println(objInput.readUTF());
System.out.println(objInput.readObject());package Io_;
import java.io.FileInputStream;
import java.io.ObjectInputStream;
import
/**
* @author Akaashi
* @version 1.0
*/
public class _04 {
public static void main(String[] args) throws Exception{
ObjectInputStream objInput = new ObjectInputStream(new FileInputStream("D://data.dat"));
System.out.println(objInput.readInt());
System.out.println(objInput.readChar());
System.out.println(objInput.readUTF());
System.out.println(objInput.readObject());
People a = (People)objInput.readObject();
//希望使用people的方法需要向下转型
a.as();//注意,这里会出现EOFException问题
// 在之前的代码中我们可以看到people的访问修饰符是默认的
// 所以这里不能使用people的方法
}
}
我们有三种方法解决这个问题
-
将people类的信息粘贴到输入的地方 , 此时我们需要将类重新保存
-
将people类公有化成public
-
将people类import
对象包装流使用细节
- 读写顺序要一致
- 可以在可序列化对象中加入 serialVersionUID 属性 , 如果之后有类的内容更新 , 有这个属性会让jvm认为还是这个类 , 只不过版本修改了
- static, transient ( 短暂的 ) 修饰的属性无法序列化 , 无法被保存
class People implements Serializable {
String name;
int age;
private static final long serialVersionUID = 1L;
static String sex;
transient String adess;
//最后读出来的是
//People{name='cw', age=24, adess='null'sex=null}
- 需要序列化对象中的所有属性都可以序列化
标准输入输出流
system.in 编译类型 inputstream
运行类型 bufferedinputstream
//表示标准输入 键盘
system.out 编译类型 printstream
运行类型 printstream
//表示标准输出 显示器
System . in 就是标准输入流的对象 ,传给扫描器
转换流
将字节字符流相互转化 , 可以将乱码变成可以读的 , 当你需要指定字符写入文件的时候也可以使用转换流
文件流读取是默认utf-8 , 如果不是这个编码 , 可能会出现乱码 , 此时我们可以使用字节流读取 , 因为字节流可以指定编码读取 , 再用装换流将字节流转化成字符流
outputstream writer ( ) | 是 输入字符流 子类 |
inputstream reader ( ) | 是 输出字符流 子类 |
public class _05 {
public static void main(String[] args) throws Exception {
OutputStreamWriter gbk = new OutputStreamWriter(
new FileOutputStream("d://a.txt",true), "gbk");
//将output转化成Writer,并在创建转换流的时候传入节点流和写入编码
gbk.write("asdad");
gbk.close();
InputStreamReader inputStreamReader = new InputStreamReader(
new FileInputStream("d://a.txt"),"gbk");
//将input转化成reader,并在创建转换流的时候传入节点流和读取编码
BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
//将reader包装成buffer reader,方便读取
String data = "";
while ((data = bufferedReader.readLine()) != null) {
System.out.println(data);
}
bufferedReader.close();
}
}
打印流
只有输出流 , 毕竟是用来打印的
printstream
字节打印流 , 继承outputstream , 默认控制台输出 , 可以通过 构造器 打印到 指定资源中 , 例如 , 打印到输出流 , 字符串 ,文件

public class _07 {
public static void main(String[] args) throws FileNotFoundException {
PrintStream printStream = System.out;
printStream.print(123);//输出123
printStream.write(123);//输出123对应的acs
//用println底层就是write,但仍旧有不同
/*
public void print(int i) {
write(String.valueOf(i));
}
*/
PrintStream printStream = new PrintStream(new FileOutputStream("d:\\a.txt"));
printStream.println(12311);
//输出到文件
printStream.close();
}
}
steam.out
steam.out 是字节打印流 , 可以直接给 printstream , 默认打印在显示器上 , 可以修改打印的位置
public class _07 {
public static void main(String[] args) throws FileNotFoundException {
System.setOut(new PrintStream("d:\\a.txt"));
System.out.println(12);//输出到文件
}
}
printwriter
字符打印流 , 继承writer
properties类
用来写配置文件 , 更加灵活 , 更加方便

properties 类是 hashtable 的子类 , 用于保存键值对

【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
· AI与.NET技术实操系列(六):基于图像分类模型对图像进行分类