流在 java i/o 操作中扮演着核心角色,主要用于处理数据序列(如文件、网络连接、内存缓冲区等)。它们主要分为两大类:字节流和字符流。
核心概念
- 字节流: 以字节为单位进行读写操作 (
8-bit),适用于所有类型的数据(图片、音频、视频、文本等)。基类是inputstream和outputstream。 - 字符流: 以字符为单位进行读写操作 (
16-bit),专为处理文本数据设计,能正确处理字符编码(如utf-8,gbk)。基类是reader和writer。
常用流类及示例
1. 文件字节流 (fileinputstream / fileoutputstream)
- 用途: 读写文件中的原始字节数据。
- 示例: 复制文件
import java.io.*;
public class filecopy {
public static void main(string[] args) {
try (inputstream in = new fileinputstream("source.jpg");
outputstream out = new fileoutputstream("copy.jpg")) {
byte[] buffer = new byte[1024];
int bytesread;
while ((bytesread = in.read(buffer)) != -1) {
out.write(buffer, 0, bytesread);
}
system.out.println("文件复制完成!");
} catch (ioexception e) {
e.printstacktrace();
}
}
}
2. 缓冲字节流 (bufferedinputstream / bufferedoutputstream)
- 用途: 包装其他字节流,提供缓冲区,减少物理 i/o 次数,显著提升性能。强烈推荐使用!
- 示例: 高效读取文件
import java.io.*;
public class bufferedread {
public static void main(string[] args) {
try (fileinputstream fis = new fileinputstream("data.bin");
bufferedinputstream in = new bufferedinputstream(fis)) {
int data;
while ((data = in.read()) != -1) {
// 处理每个字节 data
}
} catch (ioexception e) {
e.printstacktrace();
}
}
}
3. 数据流 (datainputstream / dataoutputstream)
- 用途: 读写 java 基本数据类型 (
int,double,boolean,string等) 的二进制表示。 - 示例: 写入并读取基本数据类型
import java.io.*;
public class datastreamdemo {
public static void main(string[] args) {
try (dataoutputstream dos = new dataoutputstream(new fileoutputstream("data.dat"))) {
dos.writeint(100);
dos.writedouble(3.14);
dos.writeboolean(true);
dos.writeutf("你好");
} catch (ioexception e) {
e.printstacktrace();
}
try (datainputstream dis = new datainputstream(new fileinputstream("data.dat"))) {
int i = dis.readint();
double d = dis.readdouble();
boolean b = dis.readboolean();
string s = dis.readutf();
system.out.println(i + ", " + d + ", " + b + ", " + s);
} catch (ioexception e) {
e.printstacktrace();
}
}
}
4. 对象流 (objectinputstream / objectoutputstream)
- 用途: 读写实现了 serializable 接口的 java 对象的序列化/反序列化。
- 示例: 序列化对象到文件
import java.io.*;
class person implements serializable {
private string name;
private transient int age; // transient 修饰的字段不会被序列化
public person(string name, int age) {
this.name = name;
this.age = age;
}
// ... getters, setters, tostring ...
}
public class objectstreamdemo {
public static void main(string[] args) {
person person = new person("张三", 30);
try (objectoutputstream oos = new objectoutputstream(new fileoutputstream("person.dat"))) {
oos.writeobject(person);
} catch (ioexception e) {
e.printstacktrace();
}
try (objectinputstream ois = new objectinputstream(new fileinputstream("person.dat"))) {
person readperson = (person) ois.readobject();
system.out.println(readperson); // 注意 age 字段为默认值 0 (未序列化)
} catch (ioexception | classnotfoundexception e) {
e.printstacktrace();
}
}
}
5. 文件字符流 (filereader / filewriter)
- 用途: 读写文本文件内容,按字符处理。注意编码问题! 默认使用平台默认编码。
- 示例: 读取文本文件
import java.io.*;
public class filereadwrite {
public static void main(string[] args) {
try (reader reader = new filereader("input.txt");
writer writer = new filewriter("output.txt")) {
char[] buffer = new char[1024];
int charsread;
while ((charsread = reader.read(buffer)) != -1) {
writer.write(buffer, 0, charsread);
}
system.out.println("文本文件复制完成!");
} catch (ioexception e) {
e.printstacktrace();
}
}
}
6. 缓冲字符流 (bufferedreader / bufferedwriter)
- 用途: 包装其他字符流,提供缓冲区和便捷方法(如
readline()读取整行文本)。提升文本处理效率。 - 示例: 逐行读取文本文件
import java.io.*;
public class bufferedreaderdemo {
public static void main(string[] args) {
try (bufferedreader br = new bufferedreader(new filereader("input.txt"))) {
string line;
while ((line = br.readline()) != null) {
system.out.println(line);
}
} catch (ioexception e) {
e.printstacktrace();
}
}
}
7. 转换流 (inputstreamreader / outputstreamwriter)
- 用途: 桥梁作用! 将字节流转换为字符流,并可显式指定字符编码。解决乱码问题的关键。
- 示例: 按指定编码读取文件
import java.io.*;
public class encodingdemo {
public static void main(string[] args) {
try (inputstream fis = new fileinputstream("input_gbk.txt");
// 将字节流 fis 转换为字符流,并指定编码为 gbk
reader isr = new inputstreamreader(fis, "gbk");
bufferedreader br = new bufferedreader(isr)) {
string line;
while ((line = br.readline()) != null) {
system.out.println(line); // 正确显示 gbk 编码的中文
}
} catch (ioexception e) {
e.printstacktrace();
}
}
}
8. 打印流 (printstream / printwriter)
- 用途: 提供方便的打印方法 (
print,println,printf),自动将各种类型的数据转换为文本输出。system.out就是一个printstream。 - 示例: 格式化输出到文件
import java.io.*;
public class printwriterdemo {
public static void main(string[] args) {
try (printwriter pw = new printwriter(new filewriter("log.txt"))) {
pw.println("日志开始:");
pw.printf("时间: %tt%n", system.currenttimemillis());
pw.println("操作: 用户登录");
pw.println("日志结束.");
} catch (ioexception e) {
e.printstacktrace();
}
}
}
9. 管道流 (pipedinputstream / pipedoutputstream / pipedreader / pipedwriter)
- 用途: 实现线程间的通信。一个线程通过
pipedoutputstream/pipedwriter写入数据,另一个线程通过对应的pipedinputstream/pipedreader读取数据。必须连接使用! - 示例: 线程间通信
import java.io.*;
public class pipedstreamdemo {
public static void main(string[] args) throws ioexception {
pipedoutputstream pos = new pipedoutputstream();
pipedinputstream pis = new pipedinputstream(pos); // 连接管道
thread writerthread = new thread(() -> {
try (dataoutputstream dos = new dataoutputstream(pos)) {
dos.writeutf("hello from writer thread!");
} catch (ioexception e) {
e.printstacktrace();
}
});
thread readerthread = new thread(() -> {
try (datainputstream dis = new datainputstream(pis)) {
string message = dis.readutf();
system.out.println("reader thread received: " + message);
} catch (ioexception e) {
e.printstacktrace();
}
});
writerthread.start();
readerthread.start();
}
}
总结与选择建议
| 流类型 | 典型类 | 主要用途 | 特点/注意点 |
|---|---|---|---|
| 字节流 | fileinputstream, fileoutputstream | 原始字节数据读写 | 基础文件操作 |
bufferedinputstream, bufferedoutputstream | 提高字节流效率 | 强烈推荐包装使用 | |
datainputstream, dataoutputstream | 读写基本数据类型 | 二进制格式 | |
objectinputstream, objectoutputstream | 对象序列化/反序列化 | 对象需实现 serializable | |
pipedinputstream, pipedoutputstream | 线程间字节通信 | 必须成对连接 | |
| 字符流 | filereader, filewriter | 文本文件读写 | 注意编码(默认平台编码) |
bufferedreader, bufferedwriter | 提高字符流效率,支持readline() | 推荐用于文本处理 | |
inputstreamreader, outputstreamwriter | 字节流->字符流转换,指定编码 | 解决乱码的关键 | |
printstream, printwriter | 格式化打印输出 | system.out 是 printstream | |
pipedreader, pipedwriter | 线程间字符通信 | 必须成对连接 |
选择原则:
- 数据类型: 处理二进制数据(图片、音频等)用字节流;处理文本数据优先考虑字符流。
- 性能: 使用
bufferedxxx包装流提高效率。 - 功能: 根据需求选择特定功能的流(如读写基本类型用
dataxxx,序列化用objectxxx)。 - 编码: 处理文本时,务必关注编码。使用
inputstreamreader/outputstreamwriter明确指定编码。 - 资源管理: 使用
try-with-resources语句确保流正确关闭,避免资源泄漏。
总结
到此这篇关于java各种流的常见使用方法及示例的文章就介绍到这了,更多相关java常用流类示例内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!
发表评论