流(Stream)总结与实践
Java 中的流(Stream)是用于处理数据的一种强大工具。流可以分为输入流(InputStream)和输出流(OutputStream)。Java 标准库提供了丰富的流类,使得数据的读写变得更加方便。
1. 流的基本概念
流是用来表示数据传输的一个抽象概念。在 Java 中,流可以分为两种基本类型:字节流和字符流。
- 字节流:处理的是字节数据,通常用于处理二进制数据。
- 字符流:处理的是字符数据,通常用于处理文本数据。
2. 字节流
字节流主要用于处理二进制数据,例如图像、音频等。字节流的顶级接口是 InputStream
和 OutputStream
。
2.1 输入流(InputStream)
输入流用于从数据源读取数据。
- FileInputStream:从文件系统中的文件读取字节。
- ByteArrayInputStream:从字节数组读取数据。
- BufferedInputStream:包装一个
InputStream
,提供缓冲功能以提高效率。 - DataInputStream:包装一个
InputStream
,提供读取基本数据类型的功能。
2.2 输出流(OutputStream)
输出流用于向目的地写入数据。
- FileOutputStream:向文件系统中的文件写入字节。
- ByteArrayOutputStream:向字节数组写入数据。
- BufferedOutputStream:包装一个
OutputStream
,提供缓冲功能以提高效率。 - DataOutputStream:包装一个
OutputStream
,提供写入基本数据类型的功能。
3. 字符流
字符流主要用于处理文本数据。字符流的顶级接口是 Reader
和 Writer
。
3.1 输入流(Reader)
输入流用于从数据源读取字符。
- FileReader:从文件系统中的文件读取字符。
- StringReader:从字符串读取数据。
- BufferedReader:包装一个
Reader
,提供缓冲功能以提高效率。 - LineNumberReader:扩展
BufferedReader
,记录行号。
3.2 输出流(Writer)
输出流用于向目的地写入字符。
- FileWriter:向文件系统中的文件写入字符。
- StringWriter:向字符串写入数据。
- BufferedWriter:包装一个
Writer
,提供缓冲功能以提高效率。 - PrintWriter:包装一个
Writer
,提供打印功能。
4. 示例代码
下面是一些基本的示例代码,展示如何使用 Java 中的各种流。
4.1 字节流示例
import java.io.*;
public class ByteStreamExample {
public static void main(String[] args) {
String content = "Hello, World!";
// 写入字节数组
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
try (DataOutputStream dos = new DataOutputStream(byteArrayOutputStream)) {
dos.writeUTF(content);
dos.flush();
} catch (IOException e) {
e.printStackTrace();
}
// 读取字节数组
ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(byteArrayOutputStream.toByteArray());
try (DataInputStream dis = new DataInputStream(byteArrayInputStream)) {
String readContent = dis.readUTF();
System.out.println(readContent);
} catch (IOException e) {
e.printStackTrace();
}
}
}
4.2 字符流示例
import java.io.*;
public class CharStreamExample {
public static void main(String[] args) {
String content = "Hello, World!";
// 写入字符串
StringWriter stringWriter = new StringWriter();
try (PrintWriter pw = new PrintWriter(stringWriter)) {
pw.println(content);
pw.flush();
}
// 读取字符串
String readContent;
try (StringReader sr = new StringReader(stringWriter.toString())) {
char[] buffer = new char[content.length()];
sr.read(buffer);
readContent = new String(buffer);
System.out.println(readContent);
} catch (IOException e) {
e.printStackTrace();
}
}
}
4.3 读取网络资源
import java.io.InputStream;
import java.net.URL;
import java.nio.charset.StandardCharsets;
public class URLReader {
public static void main(String[] args) {
URL url = null;
InputStream is = null;
try {
url = new URL("http://example.com");
is = url.openStream();
while (true) {
int rd = is.read();
if (rd == -1) {
break;
}
System.out.print((char)rd);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if(is != null) {
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
4.4 异常处理与流的关闭
public class AutoCloseExample {
public static void main(String[] args) {
// 使用try-with-resources自动关闭流
try (BufferedReader br = new BufferedReader(new FileReader("src/input.txt"))) {
String line = br.readLine();
while (line != null) {
System.out.println(line);
line = br.readLine();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
5. 注意事项
- 关闭资源:使用流时,一定要记得关闭打开的流资源,以避免内存泄漏。可以使用
try-with-resources
语句来自动关闭流。 - 异常处理:处理流时经常需要捕获和处理
IOException
。 - 缓冲:使用缓冲流 (
BufferedInputStream
和BufferedOutputStream
) 可以显著提高读写效率。