在Java编程的广阔天地中,数据的流动如同一条条看不见的河流,滋养着程序的生命力。而流(Stream)作为数据传输的核心机制,承载着数据的读写重任。今天,我们将深入探讨字节流与字符流的精妙之处,解锁它们背后的编程艺术。
第一章:字节流的基石 —— 构建数据的桥梁
字节流是Java中用于处理二进制数据的基础,它们以8位字节的形式传输数据。在Java标准库中,java.io.InputStream
和java.io.OutputStream
是所有字节流的根类,提供了读取和写入数据的基本方法。
1.1 文件输入/输出流
FileInputStream
和FileOutputStream
是最常用的字节流,用于读写文件系统中的数据。
示例:读取文件内容
import java.io.FileInputStream;
import java.io.IOException;
public class FileInputStreamExample {
public static void main(String[] args) {
try (FileInputStream fis = new FileInputStream("path/to/file.bin")) {
byte[] buffer = new byte[1024];
int bytesRead;
while ((bytesRead = fis.read(buffer)) != -1) {
System.out.println(new String(buffer, 0, bytesRead));
}
} catch (IOException e) {
System.err.println("读取文件失败:" + e.getMessage());
}
}
}
1.2 缓冲字节流
为了提高性能,BufferedInputStream
和BufferedOutputStream
提供了带有内部缓冲区的字节流,减少了系统调用的频率。
示例:使用缓冲字节流
import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.IOException;
public class BufferedInputStreamExample {
public static void main(String[] args) {
try (BufferedInputStream bis = new BufferedInputStream(new FileInputStream("path/to/file.bin"))) {
int data;
while ((data = bis.read()) != -1) {
System.out.print((char) data);
}
} catch (IOException e) {
System.err.println("读取文件失败:" + e.getMessage());
}
}
}
第二章:字符流的篇章 —— 文本的优雅表达
字符流专门用于处理文本数据,它们以字符为单位进行读写,通常使用java.io.Reader
和java.io.Writer
作为基类。
2.1 字符输入/输出流
FileReader
和FileWriter
是字符流中用于文件读写的常见实现。
示例:写入文本到文件
import java.io.FileWriter;
import java.io.IOException;
public class FileWriterExample {
public static void main(String[] args) {
try (FileWriter writer = new FileWriter("path/to/file.txt")) {
writer.write("Hello, world!");
writer.flush();
} catch (IOException e) {
System.err.println("写入文件失败:" + e.getMessage());
}
}
}
2.2 缓冲字符流
BufferedReader
和BufferedWriter
提供了一种高效的方式来读写字符数据,内置的缓冲区可以显著提高性能。
示例:逐行读取文本文件
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
public class BufferedReaderExample {
public static void main(String[] args) {
try (BufferedReader reader = new BufferedReader(new FileReader("path/to/file.txt"))) {
String line;
while ((line = reader.readLine()) != null) {
System.out.println(line);
}
} catch (IOException e) {
System.err.println("读取文件失败:" + e.getMessage());
}
}
}
第三章:流的高级应用 —— 装饰器模式与自定义流
Java中的流设计采用了装饰器模式,允许在已有的流上添加额外的功能而不改变其接口。
3.1 装饰器模式示例
例如,PrintStream
就是一个装饰器,它可以将字节流转换为打印流,提供方便的格式化输出方法。
示例:使用PrintStream
import java.io.PrintStream;
public class PrintStreamExample {
public static void main(String[] args) {
try (PrintStream ps = new PrintStream(System.out)) {
ps.printf("The answer is %d\n", 42);
}
}
}
3.2 自定义流的封装
你还可以创建自己的流类来满足特定需求,如压缩流GZIPOutputStream
和GZIPInputStream
,或者加密流等。
示例:创建自定义计数输出流
import java.io.FilterOutputStream;
import java.io.IOException;
import java.io.OutputStream;
public class CountingOutputStream extends FilterOutputStream {
private int count = 0;
public CountingOutputStream(OutputStream out) {
super(out);
}
@Override
public void write(int b) throws IOException {
super.write(b);
count++;
}
public int getCount() {
return count;
}
}
// 使用示例
public class UseCountingOutputStream {
public static void main(String[] args) {
try (OutputStream out = new CountingOutputStream(System.out)) {
out.write("Hello, World!".getBytes());
CountingOutputStream cos = (CountingOutputStream) out;
System.out.println("字符总数:" + cos.getCount());
} catch (IOException e) {
System.err.println("写入时发生错误:" + e.getMessage());
}
}
}
第四章:流的管理 —— 资源释放与异常处理
在使用流时,资源管理和异常处理至关重要。Java 7引入了try-with-resources语句,自动关闭实现了AutoCloseable
接口的资源,简化了代码。
示例:使用try-with-resources
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
public class TryWithResourcesExample {
public static void main(String[] args) {
try (BufferedReader reader = new BufferedReader(new FileReader("path/to/file.txt"))) {
String line;
while ((line = reader.readLine()) != null) {
System.out.println(line);
}
} catch (IOException e) {
System.err.println("读取文件失败:" + e.getMessage());
}
}
}