Java I/O流的装饰流
按照Java 输入与输出(I/O)流的处理功能:I/O流可分为低级的节点流和高级的装饰流(又称处理流)。
- 节点流是直接从数据源(数据源可以是文件、数组、内存或网络)读/写数据的输入输出流;
节点流的示意图:
- 装饰流(又称处理流),是指用于对一个已存在的输入输出流进行装饰的流,装饰流在不改变数据信息的情况下添加额外的增强功能。因为装饰流不会直接连接到实际的数据源,不能够直接获取数据,所以构建一个装饰流时,需要在构造函数中传入一个节点流。装饰流可进行多层嵌套装饰。
例如,BufferedInputStream是FileInputStream的装饰流,它为文件输入流提供缓冲功能,从而提高读取文件的效率。
Java的装饰流可对节点流或处理流进行的装饰,以提高性能或增加功能。装饰流可以分为两类:
- 字节处理流:BufferedInputStream,BufferedOutputStream,DataInputStream,DataOutputStream等。
- 字符处理流:BufferedReader,BufferedWriter,InputStreamReader,OutputStreamWriter等。
常见的装饰流都属于过滤流,例如:
一、缓冲流
缓冲流是Java I/O中的一个重要概念,它可以提高文件读写的性能。
由于磁盘的IO处理速度远低于内存的读写速度。
为了提高文件读写性能,我们可以使用缓冲流。缓冲流使用内存缓冲区,可以一次性读取或写入大量数据,从而减少与磁盘的交互次数,提高整体性能。
缓冲流有两种类型:缓冲字节流和缓冲字符流。
缓冲字节流包括BufferedInputStream和BufferedOutputStream,而缓冲字符流包括BufferedReader和BufferedWriter。
缓冲流是装饰流(处理流),不能直接访问数据源,必须使用节点流作为参数,通过节点流的桥梁实现访问数据源的目的。
下面是一个字节缓冲流的演示例程【文件拷贝程序】:
package IOStream;
import java.io.*;
public class BufferedStreamDemo {
public static void copyFileWithBuffered(String srcPath,String destPath) {
File src = new File(srcPath);
File dest = new File(destPath);
byte[] buffer = new byte[1024];
int len;
try(BufferedInputStream bis = new BufferedInputStream(new FileInputStream(src));
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(dest))){
while((len = bis.read(buffer)) != -1){
bos.write(buffer,0,len);
}
} catch (IOException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
String sPath = "D:/src/mp4/九寨沟风景.mp4";
String dPath = "D:/src/mp4/九寨沟风景B.mp4";
copyFileWithBuffered(sPath, dPath);
System.out.println("文件复制成功!");
}
}
测试结果:
二、数据流
DataInputStream和DataOutputStream是 Java的数据流,数据流是一个装饰流(处理流)。数据流在读取和写入时的顺序要一致。否则,读取的数据必定是错误的,会造成乱码。
数据流DataInputStream和DataOutputStream扩展了基本输入输出流读取基本数据类型和String类型数据的功能。数据流能以一种与平台无关的方式,直接从字节输入读取或向字节输出流写出Java基本类型和String类型的数据,常用于网络传输。
数据输出流DataOutputStream
DataOutputStream继承自FilterOutputStream,而 FilterOutputStream 又继承了 OutputStream。数据输出流拥有基本数据类型的写入操作。其writeUTF(String text)方法可将字符串写入数据输出流。但它不能直接连接数据源,它只能用于装饰节点流。
DataOutputStream定义了各种数据类型的写入方法write()方法,用于写入 Java 基础数据类型的数据和String数据:
数据输入流DataInputStream
DataInputStream继承自FilterInputStream,而 FilterInputStream 又继承了 InputStream,该数据输入流拥有基本数据类型的数据读取操作。使用readUTF()方法可从数据输入流中读取字符串。
DataInputStream中定义了各种数据类型的读取方法read(),用于读取 Java 基础数据类型的数据和String型的数据:
下面是一个演示例程:
package file;
import java.io.*;
public class DataIOTest {
public static void main(String[] args) {
String path = "D:/src/tmp/testFile.txt";
try (DataOutputStream dos = new DataOutputStream(new FileOutputStream(new File(path)));
DataInputStream dis = new DataInputStream(new FileInputStream(new File(path)))) {
dos.writeInt(128);
dos.writeBoolean(true);
dos.writeDouble(3.1416);
dos.writeUTF("天佑中华!");
dos.flush();
int i = dis.readInt();
boolean flag = dis.readBoolean();
double d = dis.readDouble();
String tempUTF = dis.readUTF();
System.out.println(i+" : "+flag+" : "+d+" : "+tempUTF);
} catch (Exception e) {
e.printStackTrace();
}
}
}
三、打印流
Java中的打印流可分为打印流(PrintStream)和打印写入器(PrintWriter),是两个用于输出信息到文本的类。
字节打印流(PrintStream)
PrintStream可以以一个节点流(FileOutputStream,ByteArrayOutputStream,或其他输出流)作为参数构造,并且提供了一系列的print和println方法用于输出各种类型的数据。
先请看一个PrintStream打印流的演示例程PrintStreamDemo:
package IOStream;
/***
* @author QiuGen
* @description 打印流(PrintStream)演示例程PrintStreamDemo
* 实现两个功能:
* 1,方法printToSystemOut():使用PrintStream打印到控制台;
* 2,方法printToFile():使用PrintStream打印到文件。
* @date 2024/10/20
* ***/
import java.io.FileOutputStream;
import java.io.PrintStream;
public class PrintStreamDemo {
static String poem[] = { "《凉州词》王翰",
"葡萄美酒夜光杯,","欲饮琵琶马上催。",
"醉卧沙场君莫笑,","古来征战几人回。"};
/***使用PrintStream打印到控制台***/
public static void printToSystemOut() {
PrintStream ps = System.out; // 获取标准输出流
for (String line : poem) {
ps.println(line); // 打印字符串
}
ps.print("\n这首诗的行数:");
ps.println(poem.length); // 打印数字
}
/***使用PrintStream打印到文件***/
public static void printToFile() {
String path = "D:/temp/凉州词.txt";
try(FileOutputStream out = new FileOutputStream(path);
PrintStream ps = new PrintStream(out)) {
for (String line : poem) {
ps.println(line); // 打印字符串
}
ps.print("\n这首诗的行数:");
ps.println(poem.length); // 打印数字
} catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
printToSystemOut();//打印到控制台
PrintStreamDemo.printToFile(); //打印到文件
}
}
字节打印流(PrintStream)演示例程PrintStreamDemo测试效果图:
打印流PrintStream的应用——输出重定向
Java系统预定义了三个标准输入/输出流,两个对象System.in和System.out,分别代表来自键盘的标准输入和往屏幕的标准输出,另一个标准错误输出流System.err对象也向屏幕输出。
System.out和System.err是标准输出流和标准错误输出流,是OutputStream实现类PrintStream类的实例。
什么是输出重定向?
输出重定向指的是将原本应该输出到标准输出(System.out)设备(如控制台或屏幕)的信息,改为输出到指定的文件或其他输出流中。这种机制在日志记录、错误信息捕获、数据持久化等场景中非常有用。
如果要将标准输出重定向输出到一个文件,需要传递一个代表文件的PrintStream对象来调用setOut()方法。重定向例程IoRedirectDemo如下:
package file;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintStream;
public class IoRedirectDemo {
public static void main(String[] args) throws IOException {
File outFile = new File("D:/temp/stdout.log");
PrintStream ps = new PrintStream(new FileOutputStream(outFile));
System.out.println(outFile.getAbsolutePath());
System.setOut(ps); //设置标准输出重定向至文件
//以下信息本来是输出到标准输出(屏幕)的,重定向后输出至文件中
System.out.println("安得广厦千万间,大庇天下寒士俱欢颜。");
System.out.println("Java I/O 重定向演示!");
// 重定向结束后,记得关闭ps
ps.close();
}
} //IoRedirectDemo例程结束。
重定向IoRedirectDemo例程测试效果图,重定向输出产生的文件: