文章目录
- 类层次结构
- 1. `java.io` 包
- 整体示意图
- 核心类
- 字节流(Byte Stream)
- 字符流(Character Stream)
- 其他辅助类
- 2. `java.nio` 包
- 示意图
- 核心类
- 文件操作
- 总结
- 字符流读写
- 1. 字符流的核心类
- 1.1 `Reader` 和 `Writer`
- 2. 常用的字符流类
- 2.1 字符输入流
- 2.2 字符输出流
- 3. 示例代码
- 3.1 读取文本文件
- 3.2 写入文本文件
- 4. 使用 `InputStreamReader` 和 `OutputStreamWriter`
- 4.1 从字节流读取字符
- 4.2 向字节流写入字符
- 5. 使用 `PrintWriter`
- 总结
- 字节流读写
- 1. 字节流的核心类
- 1.1 输入流
- 1.2 输出流
- 2. 示例代码
- 2.1 读取二进制文件
- 2.2 写入二进制文件
- 2.3 使用 `DataInputStream` 和 `DataOutputStream`
- 3. 使用 `InputStreamReader` 和 `OutputStreamWriter`
- 总结
- nio读写
- 1. NIO 的核心组件
- 1.1 缓冲区(Buffer)
- 1.2 通道(Channel)
- 1.3 选择器(Selector)
- 2. 示例代码
- 2.1 读取文本文件
- 2.2 写入文本文件
- 2.3 使用 `FileChannel` 读写文件
- 2.4 使用 `Selector` 进行网络编程
- 总结
类层次结构
Java 的 I/O 类库提供了丰富的 API 来处理输入/输出操作,包括文件读写、网络通信等。Java 的 I/O 类库主要分为两个部分:java.io
包和 java.nio
包。下面详细介绍这两个包中的核心类及其结构。
1. java.io
包
java.io
包是 Java 最初提供的 I/O 操作基础库,它主要基于流(Stream)的概念。java.io
包中的类大多采用阻塞式的 I/O 模型。
整体示意图
核心类
- InputStream/OutputStream:所有的字节流类都是从这两个抽象类派生出来的。
InputStream
:表示字节输入流。OutputStream
:表示字节输出流。
- Reader/Writer:所有的字符流类都是从这两个抽象类派生出来的。
Reader
:表示字符输入流。Writer
:表示字符输出流。
字节流(Byte Stream)
- FileInputStream/FileOutputStream:用于读写文件。
- ByteArrayInputStream/ByteArrayOutputStream:用于在内存中读写字节数组。
- PipedInputStream/PipedOutputStream:用于线程间的通信。
- FilterInputStream/FilterOutputStream:过滤流,用于包装其他流并提供附加功能。
字符流(Character Stream)
- FileReader/FileWriter:用于读写文件,以字符为单位。
- StringReader/StringWriter:用于在内存中读写字符串。
- BufferedReader/BufferedWriter:带缓冲区的字符流,提高读写效率。
- InputStreamReader/OutputStreamWriter:用于将字节流转换为字符流。
- PrintWriter:用于格式化输出。
其他辅助类
- DataInputStream/DataOutputStream:用于读写基本数据类型。
- ObjectInputStream/ObjectOutputStream:用于序列化和反序列化对象。
- SequenceInputStream:合并多个输入流。
2. java.nio
包
java.nio
包提供了基于通道(Channel)和缓冲区(Buffer)的新 I/O 操作,主要用于提高 I/O 操作的性能。java.nio
包中的类通常是非阻塞式的,更适合于处理大量并发连接的场景。
示意图
核心类
-
Buffer:缓冲区,用于存储数据。
ByteBuffer
:存储字节数据。CharBuffer
:存储字符数据。IntBuffer
:存储整型数据。FloatBuffer
:存储浮点型数据。- 等等。
-
Channel:通道,用于连接 Buffer 和实际的 I/O 设备。
FileChannel
:用于文件 I/O。DatagramChannel
:用于 UDP 通信。SocketChannel
:用于 TCP 通信。ServerSocketChannel
:用于监听 TCP 连接。
-
Selector:选择器,用于多路复用 I/O 操作,管理多个 Channel。
文件操作
Files
:提供静态方法来简化文件操作。Paths
:提供静态方法来创建和操作路径。Path
:表示文件系统的路径。
总结
java.io
包提供了一系列基于流的 I/O 操作,适用于简单的文件读写和网络通信。而 java.nio
包则提供了更高性能的 I/O 操作,适用于需要处理大量并发连接的应用场景。在实际开发中,可以根据具体的性能需求和技术背景选择合适的 I/O 模型。
字符流读写
Java 中的字符流(Character Stream)主要用于处理文本数据,因为它们以字符而不是字节的形式处理数据。字符流通常使用 java.io
包中的 Reader
和 Writer
类及其子类来实现。字符流非常适合用于处理文本文件,因为它们可以方便地处理 Unicode 字符。
1. 字符流的核心类
1.1 Reader
和 Writer
Reader
:这是所有字符输入流的超类。Writer
:这是所有字符输出流的超类。
2. 常用的字符流类
2.1 字符输入流
FileReader
:用于从文件中读取字符。StringReader
:用于从字符串中读取字符。BufferedReader
:带缓冲的字符输入流,提高了读取效率。InputStreamReader
:用于将字节流转换成字符流。
2.2 字符输出流
FileWriter
:用于向文件中写入字符。StringWriter
:用于向字符串中写入字符。BufferedWriter
:带缓冲的字符输出流,提高了写入效率。OutputStreamWriter
:用于将字符流转换成字节流。PrintWriter
:用于格式化输出,常用于标准输出。
3. 示例代码
3.1 读取文本文件
使用 FileReader
和 BufferedReader
读取文本文件:
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
public class ReadTextFile {
public static void main(String[] args) {
String filePath = "/path/to/your/file.txt";
try (BufferedReader reader = new BufferedReader(new FileReader(filePath))) {
String line;
while ((line = reader.readLine()) != null) {
System.out.println(line);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
3.2 写入文本文件
使用 FileWriter
和 BufferedWriter
写入文本文件:
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
public class WriteTextFile {
public static void main(String[] args) {
String filePath = "/path/to/your/file.txt";
try (BufferedWriter writer = new BufferedWriter(new FileWriter(filePath))) {
writer.write("Hello, World!");
writer.newLine(); // 添加新行
writer.write("This is a test file.");
} catch (IOException e) {
e.printStackTrace();
}
}
}
4. 使用 InputStreamReader
和 OutputStreamWriter
有时候,我们需要将字节流转换为字符流,这时可以使用 InputStreamReader
和 OutputStreamWriter
。
4.1 从字节流读取字符
使用 InputStreamReader
从字节流中读取字符:
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.FileInputStream;
import java.io.IOException;
public class ReadFromByteStream {
public static void main(String[] args) {
String filePath = "/path/to/your/file.txt";
try (BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(filePath)))) {
String line;
while ((line = reader.readLine()) != null) {
System.out.println(line);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
4.2 向字节流写入字符
使用 OutputStreamWriter
向字节流中写入字符:
import java.io.BufferedWriter;
import java.io.OutputStreamWriter;
import java.io.FileOutputStream;
import java.io.IOException;
public class WriteToByteStream {
public static void main(String[] args) {
String filePath = "/path/to/your/file.txt";
try (BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(filePath)))) {
writer.write("Hello, World!");
writer.newLine(); // 添加新行
writer.write("This is a test file.");
} catch (IOException e) {
e.printStackTrace();
}
}
}
5. 使用 PrintWriter
PrintWriter
类提供了一些方便的方法来格式化输出,通常用于标准输出或文件输出。
import java.io.PrintWriter;
import java.io.FileWriter;
import java.io.IOException;
public class UsePrintWriter {
public static void main(String[] args) {
String filePath = "/path/to/your/file.txt";
try (PrintWriter writer = new PrintWriter(new FileWriter(filePath))) {
writer.println("Hello, World!");
writer.println("This is a test file.");
} catch (IOException e) {
e.printStackTrace();
}
}
}
总结
字符流非常适合处理文本数据,特别是在需要处理 Unicode 字符时。通过使用 Reader
和 Writer
及其子类,可以方便地实现文本文件的读写操作。此外,通过使用 InputStreamReader
和 OutputStreamWriter
,还可以将字节流转换为字符流,从而更好地处理文本数据。
字节流读写
Java 中的字节流(Byte Stream)主要用于处理二进制数据,如图像、音频、视频等非文本数据。字节流是以字节为单位进行读写的,通常使用 java.io
包中的 InputStream
和 OutputStream
类及其子类来实现。
1. 字节流的核心类
1.1 输入流
InputStream
:这是所有字节输入流的超类。FileInputStream
:用于从文件中读取字节。ByteArrayInputStream
:用于从字节数组中读取字节。PipedInputStream
:用于线程间通信。FilterInputStream
:过滤流,用于包装其他流并提供附加功能。BufferedInputStream
:带缓冲区的字节输入流,提高了读取效率。DataInputStream
:用于读取基本数据类型。
1.2 输出流
OutputStream
:这是所有字节输出流的超类。FileOutputStream
:用于向文件中写入字节。ByteArrayOutputStream
:用于向字节数组中写入字节。PipedOutputStream
:用于线程间通信。FilterOutputStream
:过滤流,用于包装其他流并提供附加功能。BufferedOutputStream
:带缓冲区的字节输出流,提高了写入效率。DataOutputStream
:用于写入基本数据类型。
2. 示例代码
2.1 读取二进制文件
使用 FileInputStream
和 BufferedInputStream
读取二进制文件:
import java.io.FileInputStream;
import java.io.BufferedInputStream;
import java.io.IOException;
public class ReadBinaryFile {
public static void main(String[] args) {
String filePath = "/path/to/your/file.bin";
try (BufferedInputStream bis = new BufferedInputStream(new FileInputStream(filePath))) {
int data;
while ((data = bis.read()) != -1) {
System.out.printf("%02X ", data); // 以十六进制格式打印每个字节
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
2.2 写入二进制文件
使用 FileOutputStream
和 BufferedOutputStream
写入二进制文件:
import java.io.FileOutputStream;
import java.io.BufferedOutputStream;
import java.io.IOException;
public class WriteBinaryFile {
public static void main(String[] args) {
String filePath = "/path/to/your/file.bin";
byte[] bytes = {0x00, 0x01, 0x02, 0x03, 0x04};
try (BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(filePath))) {
bos.write(bytes);
} catch (IOException e) {
e.printStackTrace();
}
}
}
2.3 使用 DataInputStream
和 DataOutputStream
使用 DataInputStream
和 DataOutputStream
来读写基本数据类型:
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
public class DataIOExample {
public static void main(String[] args) {
String filePath = "/path/to/your/datafile.bin";
// 写入数据
try (DataOutputStream dos = new DataOutputStream(new FileOutputStream(filePath))) {
dos.writeInt(12345); // 写入整数
dos.writeDouble(3.14); // 写入双精度浮点数
dos.writeUTF("Hello, World!"); // 写入字符串
} catch (IOException e) {
e.printStackTrace();
}
// 读取数据
try (DataInputStream dis = new DataInputStream(new FileInputStream(filePath))) {
int intValue = dis.readInt(); // 读取整数
double doubleValue = dis.readDouble(); // 读取双精度浮点数
String stringValue = dis.readUTF(); // 读取字符串
System.out.println("Read values:");
System.out.println("Integer: " + intValue);
System.out.println("Double: " + doubleValue);
System.out.println("String: " + stringValue);
} catch (IOException e) {
e.printStackTrace();
}
}
}
3. 使用 InputStreamReader
和 OutputStreamWriter
有时候,需要将字节流转换为字符流,可以使用 InputStreamReader
和 OutputStreamWriter
:
import java.io.InputStream;
import java.io.OutputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
public class ByteToCharConversion {
public static void main(String[] args) {
String filePath = "/path/to/your/file.txt";
// 读取字符
try (BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(filePath)))) {
String line;
while ((line = reader.readLine()) != null) {
System.out.println(line);
}
} catch (IOException e) {
e.printStackTrace();
}
// 写入字符
try (BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(filePath)))) {
writer.write("Hello, World!");
writer.newLine(); // 添加新行
writer.write("This is a test file.");
} catch (IOException e) {
e.printStackTrace();
}
}
}
总结
字节流非常适合处理二进制数据,通过使用 InputStream
和 OutputStream
及其子类,可以方便地实现二进制文件的读写操作。此外,通过使用 DataInputStream
和 DataOutputStream
,还可以方便地读写基本数据类型。如果需要将字节流转换为字符流,可以使用 InputStreamReader
和 OutputStreamWriter
。
nio读写
Java NIO(New Input/Output)是 Java 平台上的新一代输入/输出技术,它提供了更高效的 I/O 操作,特别是针对大数据量和高并发的应用场景。NIO 引入了缓冲区(Buffer)、通道(Channel)和选择器(Selector)等概念,使得 I/O 操作更加灵活和高效。
1. NIO 的核心组件
1.1 缓冲区(Buffer)
缓冲区用于存储数据,是 NIO 中进行数据读写的基础。常用的缓冲区包括:
ByteBuffer
:用于存储字节数据。CharBuffer
:用于存储字符数据。IntBuffer
:用于存储整型数据。FloatBuffer
:用于存储浮点型数据。DoubleBuffer
:用于存储双精度浮点型数据。ShortBuffer
:用于存储短整型数据。LongBuffer
:用于存储长整型数据。
1.2 通道(Channel)
通道用于连接缓冲区和实际的 I/O 设备(如磁盘、网络等)。常用的通道包括:
FileChannel
:用于文件 I/O。DatagramChannel
:用于 UDP 通信。SocketChannel
:用于 TCP 通信。ServerSocketChannel
:用于监听 TCP 连接。
1.3 选择器(Selector)
选择器用于多路复用 I/O 操作,可以同时监听多个通道上的事件(如可读、可写等)。
2. 示例代码
2.1 读取文本文件
使用 NIO 读取文本文件:
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.nio.charset.StandardCharsets;
public class ReadTextFileWithNIO {
public static void main(String[] args) {
String filePath = "/path/to/your/file.txt";
try {
// 使用 Files.readAllLines 读取整个文件
List<String> lines = Files.readAllLines(Paths.get(filePath), StandardCharsets.UTF_8);
for (String line : lines) {
System.out.println(line);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
2.2 写入文本文件
使用 NIO 写入文本文件:
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.nio.charset.StandardCharsets;
public class WriteTextFileWithNIO {
public static void main(String[] args) {
String filePath = "/path/to/your/file.txt";
String content = "Hello, World!\nThis is a test file.";
try {
// 使用 Files.write 写入整个文件
Files.write(Paths.get(filePath), content.getBytes(StandardCharsets.UTF_8));
} catch (IOException e) {
e.printStackTrace();
}
}
}
2.3 使用 FileChannel
读写文件
使用 FileChannel
和 Buffer
读写文件:
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
public class FileChannelExample {
public static void main(String[] args) {
String filePath = "/path/to/your/file.bin";
// 写入数据
try (FileChannel channel = FileChannel.open(Paths.get(filePath), StandardOpenOption.WRITE, StandardOpenOption.CREATE)) {
ByteBuffer buffer = ByteBuffer.allocate(1024); // 创建缓冲区
buffer.put("Hello, World!".getBytes()); // 将数据放入缓冲区
buffer.flip(); // 切换到读取模式
channel.write(buffer); // 写入数据
} catch (IOException e) {
e.printStackTrace();
}
// 读取数据
try (FileChannel channel = FileChannel.open(Paths.get(filePath), StandardOpenOption.READ)) {
ByteBuffer buffer = ByteBuffer.allocate(1024); // 创建缓冲区
int bytesRead = channel.read(buffer); // 读取数据
if (bytesRead > 0) {
buffer.flip(); // 切换到读取模式
byte[] data = new byte[buffer.limit()];
buffer.get(data); // 从缓冲区获取数据
System.out.println(new String(data)); // 打印数据
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
2.4 使用 Selector
进行网络编程
使用 Selector
监听 TCP 连接:
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
public class SelectorExample {
public static void main(String[] args) {
int port = 1234;
try {
ServerSocketChannel serverChannel = ServerSocketChannel.open();
serverChannel.socket().bind(new InetSocketAddress(port));
serverChannel.configureBlocking(false);
Selector selector = Selector.open();
serverChannel.register(selector, SelectionKey.OP_ACCEPT);
while (true) {
int readyChannels = selector.select();
if (readyChannels == 0) continue;
for (SelectionKey key : selector.selectedKeys()) {
if (key.isAcceptable()) {
ServerSocketChannel ssc = (ServerSocketChannel) key.channel();
SocketChannel clientChannel = ssc.accept();
clientChannel.configureBlocking(false);
clientChannel.register(selector, SelectionKey.OP_READ);
} else if (key.isReadable()) {
SocketChannel clientChannel = (SocketChannel) key.channel();
ByteBuffer buffer = ByteBuffer.allocate(1024);
int bytesRead = clientChannel.read(buffer);
if (bytesRead > 0) {
buffer.flip();
byte[] data = new byte[buffer.limit()];
buffer.get(data);
System.out.println(new String(data));
}
}
}
selector.selectedKeys().clear();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
总结
NIO 提供了更高效的数据读写机制,特别是对于大数据量和高并发的应用场景非常有用。通过使用 Buffer
、Channel
和 Selector
,可以实现更灵活的 I/O 操作。在实际应用中,可以根据具体的需求选择适合的 NIO 类来实现高效的数据处理。