首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

Java IO流详细分类和代码示例整理

如果把Java IO(输入/输出)流简单地分为字节流和字符流,字节流和字符流下面又有诸多子类。

这样划分既不便于理解,还容易把各个子类之间的联系切断,有必要分的再细一些,同时还需要知道类和类之间的联系,这样才能更方便理解。

Java IO流是用于处理数据传输的机制,因为传输数据的过程类似于水流,因此称为流。

Java IO流按照数据的走向,可以分为输入流和输出流,分别用于数据的读取和写入。

Java IO流按照数据传播的方式不同,可以分为磁盘操作和网络操作。

Java IO流根据操作的角色不同,可以分为节点流和处理流。

Java IO流按照数据的传输单位,可以分为字节流和字符流。

一、字节流

字节流在Java中主要用于处理二进制数据,它们可以用于读写任何类型的数据,如图像,音频,视频等。由InputStream和OutputStream两个抽象类及其子类组成,子类由InputStream、OutputStream结尾。

InputStream:所有字节输入流的超类,定义了基本的读取字节的方法。常用子类有 FileInputStream用于从文件中读取字节流数据等。

OutputStream:所有字节输出流的超类,定义了基本的写入字节的方法。常用子类有 FileOutputStream用于向文件中写入字节流数据等。

1、示例代码

FileInputStream fis = null;

FileOutputStream fos = null;

try {

// 创建文件输入流和文件输出流

fis = new FileInputStream("source.txt");

fos = new FileOutputStream("destination.txt");

// 缓冲区数组

byte[] buffer = new byte[1024];

int bytesRead;

// 读取和写入数据

while ((bytesRead = fis.read(buffer)) != -1) {

fos.write(buffer, 0, bytesRead);

}

} catch (IOException e) {

e.printStackTrace();

} finally {

try {

// 关闭资源

if (fis != null) {

fis.close();

}

if (fos != null) {

fos.close();

}

} catch (IOException e) {

e.printStackTrace();

}

}

上面的代码是把一个txt的内容拷贝到另一个txt文件。

1)创建输入输出流:使用 FileInputStream 和 FileOutputStream 创建文件输入和输出流,分别指向源文件 source.txt 和目标文件 destination.txt。

2)定义缓冲区:定义一个字节数组 buffer 作为缓冲区,大小为 1024 字节(1KB)。

3)读取和写入数据:使用 while 循环读取源文件的数据到缓冲区中,并将缓冲区中的数据写入目标文件中,直到文件结束。

4)关闭流:在 finally 块中关闭所有打开的流,以确保资源被正确释放,防止资源泄漏。

2、操作文件注意事项

为避免内存泄漏,需要使用try-catch-finally处理异常。

对于输入流来说,当文件不在物理磁盘上,会抛出FileNotFoundException。

对于输出流来说,File类的对象可以不存在,不存在时会自动创建。

二、字符流

字符流主要用于处理文本数据,它们按字符而非字节进行操作,因此更适合处理文本数据。由Reader和Writer两个抽象类及其子类组成,子类由Reader、WriterWriter结尾。

Reader:所有字符输入流的超类,定义了基本的读取字符的方法。常用子类:FileReader用于从文件中读取数据等。

Writer:所有字符输出流的超类,定义了基本的写入字符的方法。常用子类:FileWriter用于向文件中写入数据等。

示例:

FileReader reader = null;

FileWriter writer = null;

try {

// 创建文件读取器和文件写入器

reader = new FileReader("source.txt");

writer = new FileWriter("destination.txt");

// 缓冲区字符数组

char[] buffer = new char[1024];

int charsRead;

// 读取和写入数据

while ((charsRead = reader.read(buffer)) != -1) {

writer.write(buffer, 0, charsRead);

}

} catch (IOException e) {

e.printStackTrace();

} finally {

// 关闭资源...

}

1)创建读取器和写入器:使用 FileReader 和 FileWriter 创建文件读取和写入器,分别指向源文件 source.txt 和目标文件 destination.txt。

2)定义缓冲区:定义一个字符数组 buffer 作为缓冲区,大小为 1024 字符(根据实际情况可以调整)。

3)读取和写入数据:使用 while 循环逐块读取源文件的数据到缓冲区中,并将缓冲区中的数据写入目标文件中,直到文件结束。

4)关闭资源:...

三、缓冲流

缓冲流(Buffered Streams)是对字节流和字符流的增强,通过在读写过程中使用内存缓冲区来提高性能。

1、基于字节的缓冲流

BufferedInputStream 字节缓冲输入流,通过内存缓冲区来减少实际的 I/O 操作次数,从而提高读取性能。

BufferedOutputStream 字节缓冲输出流,通过内存缓冲区来减少实际的 I/O 操作次数,从而提高写入性能。

示例:

BufferedInputStream bis = null;

BufferedOutputStream bos = null;

try {

// 1、创建文件输入流和缓冲输入流

FileInputStream fis = new FileInputStream("source.txt");

bis = new BufferedInputStream(fis);

// 2、创建文件输出流和缓冲输出流

FileOutputStream fos = new FileOutputStream("destination.txt");

bos = new BufferedOutputStream(fos);

// 缓冲区数组

byte[] buffer = new byte[1024];

int bytesRead;

// 3、读取和写入数据

while ((bytesRead = bis.read(buffer)) != -1) {

bos.write(buffer, 0, bytesRead);

}

} catch (IOException e) {

e.printStackTrace();

} finally {

// 4、关闭流...

}

1)创建输入输出流:使用 FileInputStream 和 FileOutputStream 创建文件输入和输出流,分别指向源文件 source.txt 和目标文件 destination.txt。

2)包装缓冲流:用 BufferedInputStream 包装 FileInputStream,用 BufferedOutputStream 包装 FileOutputStream,提高读写效率。

3)定义缓冲区:定义一个字节数组 buffer 作为缓冲区,大小为 1024 字节(1KB)。

4)读取和写入数据:使用 while 循环读取源文件的数据到缓冲区中,并将缓冲区中的数据写入目标文件中,直到文件结束。

5)关闭流:...

2、基于字符的缓冲流

BufferedReader 字符缓冲输入流,通过内存缓冲区来减少实际的 I/O 操作次数,从而提高读取性能。

BufferedWriter 字符缓冲输出流,通过内存缓冲区来减少实际的 I/O 操作次数,从而提高写入性能。

示例:

BufferedReader reader = null;

BufferedWriter writer = null;

try {

// 创建文件读取器和缓冲读取器

FileReader fr = new FileReader("source.txt");

reader = new BufferedReader(fr);

// 创建文件写入器和缓冲写入器

FileWriter fw = new FileWriter("destination.txt");

writer = new BufferedWriter(fw);

// 缓冲区字符串

String line;

// 读取和写入数据

while ((line = reader.readLine()) != null) {

writer.write(line);

writer.newLine(); // 写入换行符

}

} catch (IOException e) {

e.printStackTrace();

} finally {

// 4、关闭流...

}

1)创建输入输出流:使用 FileReader和 FileWriter创建文件输入和输出流,分别指向源文件 source.txt 和目标文件 destination.txt。

2)包装缓冲流:用 BufferedReader包装 FileReader ,用 BufferedWriter包装 FileWriter,提高读写效率。

3)定义缓冲区:定义一个字符串line作为缓冲区。

4)读取和写入数据:使用 while 循环读取源文件的数据到缓冲区中,并将缓冲区中的数据写入目标文件中,直到文件结束。

5)关闭流:...

缓冲流的基本原理:在创建流对象时,内部会创建一个缓冲区数组(默认/缺省使用 8192个字节(8Kb)的缓冲区),通过缓冲区读写,减少系统 IO 次数,从而提高读写的效率。

4、转换流

转换流是字符流和字节流之间的桥梁,它们允许程序以字符流的形式处理字节流,同时可以指定字符集进行编码或解码。

InputStreamReader:用于将字节输入流转换为字符输入流。

OutputStreamWriter:用于将字符输出流转换为字节输出流。

示例:

InputStreamReader reader = null;

OutputStreamWriter writer = null;

try {

// 创建文件输入流和文件输出流

FileInputStream fis = new FileInputStream("source.txt");

FileOutputStream fos = new FileOutputStream("destination.txt");

// 创建字符流读取器和写入器

reader = new InputStreamReader(fis, "UTF-8");

writer = new OutputStreamWriter(fos, "UTF-8");

// 缓冲区字符数组

char[] buffer = new char[1024];

int charsRead;

// 读取和写入数据

while ((charsRead = reader.read(buffer)) != -1) {

writer.write(buffer, 0, charsRead);

}

} catch (IOException e) {

e.printStackTrace();

} finally {

// 4、关闭流...

}

1)创建文件输入输出流:使用 FileInputStream 和 FileOutputStream 分别创建指向源文件 source.txt 和目标文件 destination.txt 的字节流。

2)创建转换流读取器和写入器:使用 InputStreamReader 和 OutputStreamWriter 分别包装文件输入输出流,并指定字符编码为 “UTF-8”。

3)定义缓冲区:定义一个字符数组 buffer 作为缓冲区,大小为 1024 字符。

4)读取和写入数据:使用 while 循环读取源文件的数据到缓冲区中,并将缓冲区中的数据写入目标文件中,直到文件结束。

5)关闭流:...

5、数据流

数据流提供基本数据类型的读写。

DataInputStream:允许应用程序以机器无关的方式从底层输入流中读取基本Java数据类型的输入流。常用方法有readInt()、readFloat()、readUTF()等。

// 以数据输入流的方式进行读数据

DataInputStream dis = new DataInputStream(new FileInputStream("source.txt"));

dis.readInt();

dis.readDouble();

dis.readUTF();

如果读取的是文件,还需要先通过FileInputStream获取源文件,然后才能转换成数据输入流进行读数据操作。

DataOutputStream:允许应用程序以机器无关的方式将基本Java数据类型写入到底层输出流中。常用方法有writeInt()、writeFloat()、writeUTF()等。

// 以数据输出流的方式进行写数据

DataOutputStream dos = new DataOutputStream(new FileOutputStream("destination.txt"));

dos.write(100);

dos.writeInt(5000);

如果写入的是文件,还需要通过FileOutputStream获取目标文件,然后才能转换成数据输出流进行写入数据操作。

6、对象流

对象流提供对象的序列化和反序列化。

ObjectInputStream:用于从源文件中读取对象。

ObjectOutputStream:用于将对象写入目标文件。

import java.io.*;

class Person implements Serializable {

private static final long serialVersionUID = 1L;

private String name;

private int age;

public Person(String name, int age) {

this.name = name;

this.age = age;

}

@Override

public String toString() {

return "Person{name='" + name + "', age=" + age + '}';

}

}

public class SerializationExample {

public static void main(String[] args) {

Person person = new Person("Alice", 30);

// 序列化

try (ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("person.ser"))) {

out.writeObject(person);

} catch (IOException e) {

e.printStackTrace();

}

// 反序列化

try (ObjectInputStream in = new ObjectInputStream(new FileInputStream("person.ser"))) {

Person deserializedPerson = (Person) in.readObject();

System.out.println("反序列化后的对象: " + deserializedPerson);

} catch (IOException | ClassNotFoundException e) {

e.printStackTrace();

}

}

}

1)创建文件输入输出流:使用 FileInputStream 和 FileOutputStream 分别创建指向源文件/目标文件 person.ser。

2)序列化:使用ObjectOutputStream对对象进行序列化并输出到文件 person.ser。

3)反序列化:使用ObjectInputStream对读取到的文件进行反序列化。

4)使用 try-with-resources 语法,确保在 try 块结束时自动关闭输入输出流,避免资源泄漏。

7. 打印流

打印流是另一种特殊的流,主要用于创建格式化的输出,而不是原始的字节。这种类型的流非常适合打印输出,或者写入文本文件。

PrintStream:为其他输出流添加了功能,使它们能够方便地打印各种数据值表示形式。

PrintWriter:打印各种格式的表示形式,包括文本、字符数组、数字、日期、时间等。

String sourceFile = "source.txt"; // 请确保这个文件存在

String destinationFile = "destination.txt";

BufferedReader reader = null;

PrintWriter writer = null;

PrintStream printStream = null;

try {

// 初始化输入流

reader = new BufferedReader(new FileReader(sourceFile));

// 初始化PrintWriter输出流

writer = new PrintWriter(new FileWriter(destinationFile));

// 初始化PrintStream输出流 (用于演示目的)

printStream = new PrintStream(new FileOutputStream(destinationFile + ".ps"));

String line;

int lineNumber = 1;

// 读取源文件并写入目标文件

while ((line = reader.readLine()) != null) {

// 使用PrintWriter写入

writer.println(line);

// 使用PrintStream写入 (添加行号作为演示)

printStream.printf("Line %d: %s%n", lineNumber, line);

lineNumber++;

}

System.out.println("文件复制完成。");

} catch (FileNotFoundException e) {

System.out.println("文件未找到: " + e.getMessage());

} catch (IOException e) {

System.out.println("读写文件时发生错误: " + e.getMessage());

} finally {

// 关闭流...

}

1)创建文件输入输出流:使用 FileReader和 FileWriter分别创建指向源文件source.txt和目标文件 destination.txt。

2)包装缓冲流:用 BufferedReader 包装 FileReader提高读效率。

3)创建打印流写入器:使用 PrintStream和 PrintWriter分别创建文件输出流。

4)使用PrintWriter直接写入行内容到目标文件。

6)关闭流:...

八、最后总结

通过上面的示例,我们可以发现一个特点,有些类是直接操作数据源的,比如字节流、字符流,还有些类是间接操作数据源的,比如缓冲流、数据流、对象流和打印流。

直接从数据源或目标读写数据的,不论是文件或数组,这样的流称为节点流,又称原始流。

间接连接到数据源或目标,建立在已存在流之上的,称为处理流。

处理流又称为包装流,不能独立存在,它们必须连接到另一个流上。处理流本身不提供实际的读写能力,而是通过包装一个已存在的节点流或其他处理流来增强其功能。处理流的作用可以是数据的过滤、装饰或增强等,它们通常用于提供更高级别的功能。

把以上的流再次进行分类,常用的节点流有:

文件流:FileInputStream、FileOutputStrean、FileReader、FileWriter,直接操作文件。

字节/字符数组流:ByteArrayInputStream、ByteArrayOutputStream、CharArrayReader、CharArrayWriter,直接操作字节或字符数组。

常用的处理流:

BufferedInputStream / BufferedOutputStream、BufferedReader、BufferedWriter:提供缓冲功能,减少对底层节点流的直接访问次数,从而提升性能。

InputStreamReader / OutputStreamWriter:将字节流转换为字符流,支持字符集的指定。

DataInputStream / DataOutputStream:提供基本数据类型的读写操作。

ObjectInputStream / ObjectOutputStream:支持对象的序列化和反序列化。

PrintStream/PrintWriter:打印格式化的文本输出到目标流。

  • 发表于:
  • 原文链接https://page.om.qq.com/page/OUNFQP5A4E1IUJXjWngPaavA0
  • 腾讯「腾讯云开发者社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 cloudcommunity@tencent.com 删除。

扫码

添加站长 进交流群

领取专属 10元无门槛券

私享最新 技术干货

扫码加入开发者社群
领券