Java IO 流操作详解
一、简介
Java IO流提供了一种可以对数据进行输入输出的机制。可以把它比作是一条河流从源头流向目标地,由源文件输入到程序再由程序输出到目标文件。
1. 什么是IO流
IO即Input/Output顾名思义就是数据的输入输出,在Java中指的是java.io包中的类库,提供了一系列操作数据输入与输出的类和接口。
2. IO流的分类
Java IO流按照其功能可以分为4种类型:
- 字节流(Byte Streams):从字节流中读入或输出8位字节数据。InputStream 和 OutputStream 都是针对字节的流。
- 字符流(Character Streams):从字符流中读入或输出16位Unicode字符。Reader 和 Writer 都是针对字符的流。
- 节点流(Node Streams):Advanced 系列流,如 FileInputStream、FileOutputStream。
- 处理流(Filter Streams):Decorator 系列流,如 BufferedInputStream、BufferedOutputStream、ObjectInputStream、ObjectOutputStream。
3. IO流的作用
在Java中IO流的主要作用是将数据从一个地方传输到另一个地方。我们可以使用Java的IO流来实现从文件、控制台甚至是网络传输数据等功能。对于不同的需求,可以灵活选择不同的IO流类型。
二、Java IO流的输入操作
Java IO流提供了多种输入操作的类和接口下面将分别介绍其中的四种。
1. 文件输入流
用于从文件中读取数据可以使用 java.io.FileInputStream 类来实现。
try {
FileInputStream fis = new FileInputStream("file.txt"); // 指定文件路径
int c;
while ((c = fis.read()) != -1) { // 从文件中读取数据
System.out.print((char)c); // 输出数据到控制台
}
fis.close(); // 关闭文件流
} catch (IOException e) {
e.printStackTrace();
}
2. 字节输入流
用于从数据源中读取字节数据可以使用 java.io.InputStream 类来实现。
try {
InputStream is = new FileInputStream("file.txt"); // 指定数据源
int c;
while ((c = is.read()) != -1) { // 从数据源读取数据
System.out.print((char)c); // 输出数据到控制台
}
is.close(); // 关闭数据流
} catch (IOException e) {
e.printStackTrace();
}
3. 缓冲输入流
提供了对 IO 字节输入流的缓存机制可以使用 java.io.BufferedInputStream 类来实现
try {
InputStream is = new FileInputStream("file.txt"); // 指定数据源
BufferedInputStream bis = new BufferedInputStream(is); // 使用缓冲输入流读取数据
int c;
while ((c = bis.read()) != -1) { // 从缓冲输入流中读取数据
System.out.print((char)c); // 输出数据到控制台
}
is.close(); // 关闭数据流
} catch (IOException e) {
e.printStackTrace();
}
4. 对象输入流
用于读取对象的相关信息可以使用 java.io.ObjectInputStream 类来实现
try {
InputStream is = new FileInputStream("file.txt"); // 指定数据源
ObjectInputStream ois = new ObjectInputStream(is); // 使用对象输入流读取对象相关信息
Object obj = ois.readObject(); // 从对象输入流中读取对象相关信息并实例化为一个对象
System.out.println(obj); // 输出读取到的对象
is.close(); // 关闭数据流
} catch (IOException | ClassNotFoundException e) {
e.printStackTrace();
}
三、Java IO流的输出操作
Java IO流提供了多种输出操作的类和接口,下面将分别介绍其中的四种。
1. 文件输出流
用于向文件中写入数据可以使用 java.io.FileOutputStream 类来实现
try {
FileOutputStream fos = new FileOutputStream("file.txt"); // 指定输出文件路径
String s = "Hello, World!"; // 要写入文件的内容
byte[] bytes = s.getBytes(); // 将要写入的字符串转化为字节数组
fos.write(bytes); // 向文件中写入字节数据
fos.close(); // 关闭文件流
} catch (IOException e) {
e.printStackTrace();
}
2. 字节输出流
用于向数据源中输出字节数据可以使用 java.io.OutputStream 类来实现
try {
OutputStream os = new FileOutputStream("file.txt"); // 指定数据源
String s = "Hello, World!"; // 要写入数据源的内容
byte[] bytes = s.getBytes(); // 将要写入的字符串转化为字节数组
os.write(bytes); // 向数据源中写入字节数据
os.close(); // 关闭数据流
} catch (IOException e) {
e.printStackTrace();
}
3. 缓冲输出流
提供了对 IO 字节输出流的缓存机制可以使用 java.io.BufferedOutputStream 类来实现
try {
OutputStream os = new FileOutputStream("file.txt"); // 指定数据源
BufferedOutputStream bos = new BufferedOutputStream(os); // 使用缓冲输出流写入数据源
String s = "Hello, World!"; // 要写入数据源的内容
byte[] bytes = s.getBytes(); // 将要写入的字符串转化为字节数组
bos.write(bytes); // 向缓冲输出流中写入字节数据
bos.flush(); // 刷新流数据到文件,清空缓存
os.close(); // 关闭数据流
} catch (IOException e) {
e.printStackTrace();
}
4. 对象输出流
用于将对象信息写入输出源可以使用 java.io.ObjectOutputStream 类来实现
try {
OutputStream os = new FileOutputStream("file.txt"); // 指定数据源
ObjectOutputStream oos = new ObjectOutputStream(os); // 创建对象输出流
Object obj = new Object(); // 要写入数据源的对象
oos.writeObject(obj); // 将对象信息写入输出源
oos.flush(); // 刷新流数据到文件,清空缓存
os.close(); // 关闭数据流
} catch (IOException e) {
e.printStackTrace();
}
四、Java IO流的常用方法解析
1. 字节读写操作
1.1 FileInputStream和FileOutputStream
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
public class ByteStreamExample {
public static void main(String[] args) {
File inputFile = new File("input.txt");
File outputFile = new File("output.txt");
try (FileInputStream inputStream = new FileInputStream(inputFile);
FileOutputStream outputStream = new FileOutputStream(outputFile)) {
byte[] buffer = new byte[1024];
int length;
while ((length = inputStream.read(buffer)) != -1) {
outputStream.write(buffer, 0, length);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
以上代码实现了从input.txt文件读取数据并写入到output.txt文件中。
1.2 DataInputStream和DataOutputStream
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
public class DataStreamExample {
public static void main(String[] args) {
File inputFile = new File("input.txt");
File outputFile = new File("output.txt");
try (DataInputStream inputStream = new DataInputStream(new FileInputStream(inputFile));
DataOutputStream outputStream = new DataOutputStream(new FileOutputStream(outputFile))) {
int intValue = inputStream.readInt();
outputStream.writeInt(intValue);
boolean boolValue = inputStream.readBoolean();
outputStream.writeBoolean(boolValue);
String strValue = inputStream.readUTF();
outputStream.writeUTF(strValue);
} catch (IOException e) {
e.printStackTrace();
}
}
}
以上代码实现了从input.txt文件中读取整型、布尔型和字符串类型数据,然后将这些数据写入到output.txt文件中。
2. 按字符读写操作
2.1 FileReader和FileWriter
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
public class CharStreamExample {
public static void main(String[] args) {
File inputFile = new File("input.txt");
File outputFile = new File("output.txt");
try (FileReader reader = new FileReader(inputFile);
FileWriter writer = new FileWriter(outputFile)) {
char[] buffer = new char[1024];
int length;
while ((length = reader.read(buffer)) != -1) {
writer.write(buffer, 0, length);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
以上代码实现了从input.txt文件读取数据并写入到output.txt文件中。
2.2 BufferedReader和BufferedWriter
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
public class BufferCharStreamExample {
public static void main(String[] args) {
try (BufferedReader reader = new BufferedReader(new FileReader("input.txt"));
BufferedWriter writer = new BufferedWriter(new FileWriter("output.txt"))) {
String line;
while ((line = reader.readLine()) != null) {
writer.write(line);
writer.newLine();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
以上代码实现了从input.txt文件读取数据并写入到output.txt文件中,同时以行的形式进行读写。
3. 随机读写文件操作
3.1 RandomAccessFile
import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
public class RandomAccessFileExample {
public static void main(String[] args) {
File file = new File("file.txt");
try (RandomAccessFile randomAccessFile = new RandomAccessFile(file, "rw")) {
randomAccessFile.writeBytes("Hello World!");
randomAccessFile.seek(6);
randomAccessFile.writeBytes("Java");
} catch (IOException e) {
e.printStackTrace();
}
}
}
以上代码实现了向file.txt文件中写入"Hello World!",然后从第6个字节开始替换为"Java"。
4. 大文件读写操作
4.1 使用MappedByteBuffer
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
public class LargeFileExample {
public static void main(String[] args) {
File inputFile = new File("input.txt");
File outputFile = new File("output.txt");
try (FileInputStream inputStream = new FileInputStream(inputFile);
FileOutputStream outputStream = new FileOutputStream(outputFile)) {
FileChannel inputChannel = inputStream.getChannel();
FileChannel outputChannel = outputStream.getChannel();
MappedByteBuffer buffer = inputChannel.map(FileChannel.MapMode.READ_ONLY, 0, inputChannel.size());
outputChannel.write(buffer);
} catch (IOException e) {
e.printStackTrace();
}
}
}
以上代码实现了将input.txt文件中的数据复制到output.txt文件中,如果读取的文件太大需要使用MappedByteBuffer来减少内存开销。
五、Java NIO模块
1. NIO概述
Java NIO(New IO)是JDK1.4引入的新的IO API,能够以更高效的方式进行文件、网络读写等各种I/O操作。
2. NIO与IO的对比
3. NIO模块的核心组件
3.1 Buffer
Buffer是一个对象可以容纳一定数量的数据,并提供了一组方法用于访问这些数据。
3.2 Channel
Channel是用于进行数据读写的对象,它类似于IO流中的“管道”。
3.3 Selector
Selector用于监听多个Channel上的事件(如读、写等),并通过一个线程实现多路复用。
4. NIO模块的使用方式
4.1 读取文件数据
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import java.util.EnumSet;
public class NioExample {
public static void main(String[] args) {
Path path = Paths.get("file.txt");
try (FileChannel channel = (FileChannel) Files.newByteChannel(path, EnumSet.of(StandardOpenOption.READ))) {
ByteBuffer buffer = ByteBuffer.allocate(1024);
while (channel.read(buffer) != -1) {
buffer.flip();
while (buffer.hasRemaining()) {
System.out.print((char) buffer.get());
}
buffer.clear();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
以上代码实现了从file.txt文件中读取数据并输出到控制台。其中FileChannel的read()方法用于读取文件数据,ByteBuffer的flip()方法将缓冲区从写入状态切换到读取状态,clear()方法则用于清空缓冲区。
4.2 写入文件数据
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import java.util.EnumSet;
public class NioExample {
public static void main(String[] args) {
Path path = Paths.get("file.txt");
try (FileChannel channel = (FileChannel) Files.newByteChannel(path, EnumSet.of(StandardOpenOption.WRITE))) {
ByteBuffer buffer = ByteBuffer.wrap("Hello World!".getBytes());
channel.write(buffer);
} catch (IOException e) {
e.printStackTrace();
}
}
}
以上代码实现了向file.txt文件中写入数据“Hello World!”。其中FileChannel的write()方法用于写入文件数据,ByteBuffer的wrap()方法用于把字节数组包装成缓冲区。