一、java的IO是基于流(stream)概念的,什么是流:
在Java中,流(Stream)是一种抽象的数据传输方式,它代表了数据的序列。流可以用于表示来自各种源的数据输入,以及向各种目的地发送数据的输出。Java的IO(输入/输出)系统是基于流的概念构建的,这些流可以是字节流或字符流。
IO流,即输入/输出流(Input/Output Stream),是计算机科学中用于数据传输的一种抽象概念。在编程中,IO流允许程序以统一的方式处理数据的输入和输出,无论数据来自何处或去向何方。IO流的概念在多种编程语言中都有应用,包括Java。
(以下图片均来自转载)
#IO流的基本概念:
1. **数据流**:数据流是数据的序列,可以是输入流或输出流。输入流用于从数据源读取数据,输出流用于向数据目的地写入数据。
2. **字节流**:字节流处理原始字节数据,适用于二进制数据的读写。
3. **字符流**:字符流处理字符数据,通常用于文本数据的读写。字符流在处理文本时会涉及到字符编码的转换。
4. **节点流(Node Stream)**:直接连接到数据源或数据目的地的流,如文件流。
5. **处理流(Filter Stream)**:对其他流进行包装,提供额外功能的流,如缓冲流、转换流等。
6. **管道流**:用于线程间通信的流,允许一个线程将数据写入管道,另一个线程从管道读取数据。
# Java中的IO流:
Java的IO流主要分为两大类:字节流和字符流。Java提供了一套丰富的类库来支持不同类型的IO操作:
- **字节流**:以字节为单位进行数据的读写,如`InputStream`和`OutputStream`。
- **字符流**:以字符为单位进行数据的读写,如`Reader`和`Writer`。
Java IO流的层次结构如下:
- **InputStream/Reader**:所有输入流的基类。
- **OutputStream/Writer**:所有输出流的基类。
- **FileInputStream/FileReader**:用于从文件读取字节或字符。
- **FileOutputStream/FileWriter**:用于向文件写入字节或字符。
- **BufferedInputStream/BufferedReader**:提供缓冲区的输入流,提高读写效率。
- **DataInputStream/DataOutputStream**:提供读写基本数据类型的功能。
- **ObjectInputStream/ObjectOutputStream**:用于对象的序列化和反序列化。
- **PipedInputStream/PipedOutputStream**:用于线程间的通信。
- **RandomAccessFile**:提供对文件的随机访问。
IO流的使用可以简化数据传输的编程工作,提高代码的可读性和可维护性。通过使用IO流,开发者可以不必关心底层的数据传输细节,只需通过流的API来实现数据的读写操作。
二、 流的分类:
1. 按数据类型分类:
- 字节流(Byte Streams):处理原始字节数据,适用于二进制数据。
- 字符流(Character Streams):处理字符数据,通常用于文本数据,支持字符编码。
-
字节流,一般是带有Stream字样的,如InputStream,FileInputStream等等,这组流处理的最小单位之字节。
-
字符流,一般是带有Reader或Writer字样的,如InputStreamReader等等,它们处理的最小单位是字符。
2. 按流向分类:
- 输入流(Input Streams):用于从数据源读取数据。
- 输出流(Output Streams):用于向数据目的地写入数据。
-
输入流,模样很好记,一般情况下,输入流是带有Input字样或Reader字样的,如FileInputStream和BufferedReader等等,这些都是输入流。
-
输出流,一般情况下,是带有Output字样或Writer的,如FileOutputStream和FileWriter等等。
3. 按数据源和目的地分类:
- 节点流(Node Streams):直接连接到数据源或数据目的地的流,如文件流。
- 处理流(Filter Streams):对其他流进行包装,提供额外功能的流,如缓冲流、转换流。
4. 按功能分类:
- 缓冲流(Buffered Streams):提供内部缓冲区以提高读写效率。
- 转换流(Conversion Streams):在字节流和字符流之间进行转换。
- 数据流(Data Streams):提供读写基本数据类型的功能。
- 对象流(Object Streams):用于对象的序列化和反序列化。
- 打印流(Print Streams):提供格式化输出功能。
- 管道流(Piped Streams):用于线程间通信。
5. 按访问方式分类:
- 顺序访问流(Sequential Access Streams):数据只能顺序读取或写入。
- 随机访问流(Random Access Streams):可以随机访问数据流中的任意位置。
6. 按操作方式分类:
- 只读流(Read-only Streams):只能读取数据,不能写入。
- 只写流(Write-only Streams):只能写入数据,不能读取。
- 读写流(Read-Write Streams):既可以读取数据,也可以写入数据。
7. 特定用途的流:
- 内存映射文件流(Memory-Mapped File Streams):将文件或文件的一部分映射到内存中,提高访问速度。
- 压缩流(Compression Streams):用于数据的压缩和解压缩,如ZIP或GZIP流。
Java中的流分类:
在Java中,流的分类通常基于它们的基类和功能。Java的流类主要分为两大类:字节流和字符流,每类都有相应的输入和输出流,以及各种特殊功能的流。
- InputStream 和 OutputStream:字节流的基类。
- Reader 和 Writer:字符流的基类。
- FileInputStream、FileOutputStream、FileReader、FileWriter:用于文件的读写。
- BufferedInputStream、BufferedOutputStream、BufferedReader、BufferedWriter:提供缓冲功能的流。
- DataInputStream、DataOutputStream:用于读写基本数据类型。
- ObjectInputStream、ObjectOutputStream:用于对象的序列化和反序列化。
- PipedInputStream、PipedOutputStream:用于线程间通信。
- RandomAccessFile:提供对文件的随机访问。
每种流都有其特定的用途和特点,开发者可以根据实际需求选择合适的流类型。
三、流的使用:
1、字节流常用类的用法:
1. InputStream
:
- 抽象类,是所有输入字节流的超类。
- 提供了基本的读取字节数据的方法。
2. OutputStream
:
- 抽象类,是所有输出字节流的超类。
- 提供了基本的写入字节数据的方法。
3. FileInputStream
:
- 用于从文件中读取字节数据。
- 用法示例:
FileInputStream fis = new FileInputStream("example.bin"); int byteRead; while ((byteRead = fis.read()) != -1) { // 处理读取的字节 } fis.close();
4. FileOutputStream
:
- 用于向文件写入字节数据。
- 用法示例:
FileOutputStream fos = new FileOutputStream("output.bin"); byte[] data = "Hello, World!".getBytes(); fos.write(data); fos.close();
5. ByteArrayInputStream
:
- 包装一个字节数组,提供对数组内容的输入流访问。
- 用法示例:
byte[] byteArray = {10, 20, 30, 40}; ByteArrayInputStream bais = new ByteArrayInputStream(byteArray); int value; while ((value = bais.read()) != -1) { // 处理读取的字节 }
6. ByteArrayOutputStream
:
- 提供一个可扩展的字节数组,用于收集字节数据。
- 用法示例:
-
ByteArrayOutputStream baos = new ByteArrayOutputStream(); baos.write(72); // 写入字节数据 byte[] buffer = baos.toByteArray(); // 获取字节数组 baos.close();
7. DataInputStream
:
- 从
InputStream
读取基本数据类型。 - 用法示例:
-
DataInputStream dis = new DataInputStream(new FileInputStream("data.bin")); int number = dis.readInt(); dis.close();
8. DataOutputStream
:
- 写入基本数据类型到
OutputStream
。 - 用法示例:
-
DataOutputStream dos = new DataOutputStream(new FileOutputStream("data.bin")); dos.writeInt(123); dos.close();
9. PipedInputStream
和 PipedOutputStream
:
- 用于线程间的通信。
- 用法示例:
-
PipedOutputStream pos = new PipedOutputStream(); PipedInputStream pis = new PipedInputStream(pos); // 将pis连接到一个线程,将pos连接到另一个线程
10. SequenceInputStream
:
- 允许将多个
InputStream
合并成一个单一的输入流。 - 用法示例:
-
InputStream is1 = ...; InputStream is2 = ...; SequenceInputStream sis = new SequenceInputStream(is1, is2); while (sis.available() > 0) { int b = sis.read(); // 处理读取的字节 }
11. ObjectInputStream
和 ObjectOutputStream
:
- 用于对象的序列化和反序列化。
- 用法示例(序列化):
-
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("object.dat")); MyObject obj = new MyObject(); oos.writeObject(obj); oos.close();
12. FilterInputStream
和 FilterOutputStream
:
- 抽象类,用于添加功能到其他输入/输出流。
- 比如,
BufferedInputStream
和BufferedOutputStream
就是从这些类继承的。
注意事项:
- 总是使用
try-catch
块来捕获可能发生的IOException
。 - 使用
try-with-resources
语句来自动关闭流,避免资源泄露。 - 根据需要选择合适的字节流类,以提高代码的效率和可读性。
2.字符流常用类的用法:
1. Reader
:
- 抽象类,是所有用于读取字符数据的类的超类。
2. Writer
:
- 抽象类,是所有用于写入字符数据的类的超类。
3. FileReader
:
- 用于从文件中读取字符数据。
- 用法示例:
FileReader fr = new FileReader("example.txt"); int charRead; while ((charRead = fr.read()) != -1) { System.out.print((char) charRead); // 打印字符 } fr.close();
4. FileWriter
:
- 用于向文件写入字符数据。
- 用法示例:
FileWriter fw = new FileWriter("output.txt"); fw.write("Hello, World!"); fw.close();
5. BufferedReader
:
- 包装一个字符输入流,并提供一个字符数组缓冲区以提高效率。
- 用法示例:
BufferedReader br = new BufferedReader(new FileReader("example.txt")); String line; while ((line = br.readLine()) != null) { System.out.println(line); } br.close();
6. BufferedWriter
:
- 包装一个字符输出流,并提供一个字符数组缓冲区以提高效率。
- 用法示例:
BufferedWriter bw = new BufferedWriter(new FileWriter("output.txt")); bw.write("Hello, World!"); bw.newLine(); // 写入换行符 bw.close();
7. CharArrayReader
:
- 包装一个字符数组,并提供对数组内容的输入流访问。
- 用法示例:
char[] charArray = {'H', 'e', 'l', 'l', 'o'}; CharArrayReader car = new CharArrayReader(charArray); int value; while ((value = car.read()) != -1) { System.out.print((char) value); }
8. CharArrayWriter
:
- 提供一个可扩展的字符数组,用于收集字符数据。
- 用法示例:
CharArrayWriter cw = new CharArrayWriter(); cw.write("Hello, World!".toCharArray()); String buffer = cw.toString(); // 获取字符串 cw.close();
9. StringReader
:
- 包装一个
String
,并提供对字符串内容的输入流访问。 - 用法示例:
StringReader sr = new StringReader("Hello, World!"); int value; while ((value = sr.read()) != -1) { System.out.print((char) value); }
10. StringWriter
:
- 提供一个
String
作为字符数据的输出目的地。 - 用法示例:
StringWriter sw = new StringWriter(); sw.write("Hello, World!"); String output = sw.toString(); // 获取字符串 sw.close();
11. PipedReader
和 PipedWriter
:
- 用于线程间的字符数据通信。
- 用法示例:
PipedWriter pw = new PipedWriter(); PipedReader pr = new PipedReader(pw); // 将pr连接到一个线程,将pw连接到另一个线程
12. PrintWriter
:
- 用于打印格式化的字符数据到输出流。
- 用法示例:
PrintWriter pw = new PrintWriter(new FileWriter("output.txt")); pw.println("Hello, World!"); pw.close();
注意事项:
- 确保字符流的编码与文件的编码一致,以避免字符编码错误。
- 使用
try-with-resources
语句自动管理资源,确保流在使用后被关闭。 - 根据需要选择合适的字符流类,以提高代码的效率和可读性。
3.FilterInputStream的各种类型:
3.1 用于封装以字节为导向的InputStream
1) DataInputStream:从stream中读取基本类型(int、char等)数据。
2) BufferedInputStream:使用缓冲区
3) LineNumberInputStream:会记录input stream内的行数,然后可以调用getLineNumber()和setLineNumber(int)
4) PushbackInputStream:很少用到,一般用于编译器开发
3.2 用于封装以字符为导向的InputStream
1) 没有与DataInputStream对应的类。除非在要使用readLine()时改用BufferedReader,否则使用DataInputStream
2) BufferedReader:与BufferedInputStream对应
3) LineNumberReader:与LineNumberInputStream对应
4) PushBackReader:与PushbackInputStream对应
2.3 FilterOutStream的各种类型
3.3 用于封装以字节为导向的OutputStream
1) DataIOutStream:往stream中输出基本类型(int、char等)数据。
2) BufferedOutStream:使用缓冲区
3) PrintStream:产生格式化输出
3.4 用于封装以字符为导向的OutputStream
1) BufferedWrite:与对应
2) PrintWrite:与对应
3.5 RandomAccessFile
1) 可通过RandomAccessFile对象完成对文件的读写操作
2) 在产生一个对象时,可指明要打开的文件的性质:r,只读;w,只写;rw可读写
3) 可以直接跳到文件中指定的位置
4.流的使用涉及几个基本步骤,无论是在Java还是其他支持流的编程语言中。以下是使用流的一般步骤:
1. **创建流对象**:
确定数据源和目的地,然后创建相应的流对象。例如,如果需要从文件读取数据,则创建`FileInputStream`或`FileReader`对象。
2. **打开流**:
- 对于某些类型的流,如文件流,需要显式打开流。这通常通过调用流对象的`open()`方法来完成。
3. **读写数据**:
- 使用流对象提供的方法来读取或写入数据。对于字节流,可以使用`read()`和`write()`方法。对于字符流,可以使用`read(char[] cbuf)`、`write(String str)`等方法。
4. **处理异常**:
- IO操作可能会抛出异常,如`IOException`。使用`try-catch`块来捕获和处理这些异常。
5. **关闭流**:
- 完成数据读写后,应该关闭流以释放系统资源。这可以通过调用流对象的`close()`方法来完成。为了确保流总是被关闭,即使发生异常,可以使用`try-with-resources`语句(Java 7及以上版本)。
6. **使用装饰者模式**:
- 利用装饰者模式,可以为流添加额外的功能,如缓冲、数据转换等,而不需要修改现有的代码。
### 示例:使用Java进行文件读取和写入
以下是一个简单的Java示例,演示如何使用字符流读取和写入文件:
import java.io.*;
public class StreamExample {
public static void main(String[] args) {
// 定义文件路径
String filePathRead = "example.txt";
String filePathWrite = "output.txt";
try (BufferedReader reader = new BufferedReader(new FileReader(filePathRead));
BufferedWriter writer = new BufferedWriter(new FileWriter(filePathWrite))) {
// 读取文件内容并写入到另一个文件
String line;
while ((line = reader.readLine()) != null) {
writer.write(line);
writer.newLine(); // 写入换行符
}
System.out.println("文件读取和写入完成。");
} catch (IOException e) {
e.printStackTrace();
}
}
}
在这个示例中,我们使用了BufferedReader
和BufferedWriter
来提高文件读写的效率。使用try-with-resources
语句确保了流在使用后能够自动关闭。
注意事项:
- 确保处理所有可能的异常情况。
- 总是关闭流以释放系统资源,避免资源泄露。
- 使用适当的异常处理机制,确保程序的健壮性。
- 根据需要选择合适的流类型,以提高代码的效率和可读性。
四、在Java中,进行文件的读写操作通常涉及以下步骤:
-
创建文件输入/输出流对象:根据需要读写的文件类型(文本或二进制)和操作(读或写),选择适当的流类。
-
打开文件:对于文件流,通常在创建流对象时指定文件路径,Java会自动打开文件。
-
读写数据:使用流对象提供的方法来读取或写入数据。
-
处理异常:IO操作可能会抛出
IOException
,需要使用try-catch
块来捕获和处理这些异常。 -
关闭流:完成读写操作后,应该关闭流以释放系统资源。可以使用
try-finally
块或Java 7及以上版本的try-with-resources
语句来确保流被正确关闭。
以下是一些具体的示例:
读取文本文件:
import java.io.*;
public class StreamExample {
public static void main(String[] args) {
// 定义文件路径
String filePathRead = "example.txt";
String filePathWrite = "output.txt";
try (BufferedReader reader = new BufferedReader(new FileReader(filePathRead));
BufferedWriter writer = new BufferedWriter(new FileWriter(filePathWrite))) {
// 读取文件内容并写入到另一个文件
String line;
while ((line = reader.readLine()) != null) {
writer.write(line);
writer.newLine(); // 写入换行符
}
System.out.println("文件读取和写入完成。");
} catch (IOException e) {
e.printStackTrace();
}
}
}
写入文本文件:
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
public class WriteTextFile {
public static void main(String[] args) {
String filePath = "output.txt";
String content = "Hello, World!";
try (BufferedWriter writer = new BufferedWriter(new FileWriter(filePath))) {
writer.write(content);
} catch (IOException e) {
e.printStackTrace();
}
}
}
读取二进制文件:
import java.io.FileInputStream;
import java.io.IOException;
public class ReadBinaryFile {
public static void main(String[] args) {
String filePath = "example.bin";
byte[] fileContent = new byte[1024]; // 假设文件内容不超过1024字节
try (FileInputStream fis = new FileInputStream(filePath)) {
int bytesRead = fis.read(fileContent);
while (bytesRead != -1) {
// 处理读取的数据
System.out.println(new String(fileContent, 0, bytesRead));
bytesRead = fis.read(fileContent);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
写入二进制文件:
import java.io.FileOutputStream;
import java.io.IOException;
public class WriteBinaryFile {
public static void main(String[] args) {
String filePath = "output.bin";
byte[] data = "Hello, World!".getBytes(); // 将字符串转换为字节数组
try (FileOutputStream fos = new FileOutputStream(filePath)) {
fos.write(data);
} catch (IOException e) {
e.printStackTrace();
}
}
}
在这些示例中,使用了BufferedReader
和BufferedWriter
来提高读写效率,它们分别包装了FileReader
和FileWriter
。对于二进制文件的读写,使用了FileInputStream
和FileOutputStream
。
请注意,示例中的try-with-resources
语句确保了每个资源(在这种情况下是流)在使用后都被自动关闭。这是一种推荐的做法,因为它可以减少资源泄露的风险。
五、实例测试代码:
建立一个基本的Java项目:
在src包下面建立一个data1.txt文件空白也可以,方便观察
建议写入再读取更方便观察结果,体会两个流的不同
字节流输出流:
写数据OutputStream即测试代码:
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
public class OutputStream1 {
public static void main(String[] args) {
String data="hello!java";
FileOutputStream fileOutputStream = null;
try {
fileOutputStream = new FileOutputStream("src/data1.txt");
} catch (FileNotFoundException e) {
e.printStackTrace();
}
try {
fileOutputStream.write(data.getBytes());
} catch (IOException ioException) {
ioException.printStackTrace();
}
}
}
字节流输入流:
读数据即Inputstream测试代码:
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
public class InputStream1 {
public static void main(String[] args) {
FileInputStream fileInputStream = null;
try {
fileInputStream = new FileInputStream("src/data1.txt");//对应文件的位置
int data;
//读取文件内容
while ((data=fileInputStream.read())!=-1){
System.out.println((char) data);
}
//异常处理
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException ioException) {
ioException.printStackTrace();
}
}
}
字符流输出流:
Outputwriter字符流的测试代码:
import java.io.FileWriter;
import java.io.IOException;
public class Outputwriter {
public static void main(String[] args) throws IOException {
String data="hello!java";
FileWriter fileWriter = new FileWriter("src/data1.txt");
fileWriter.write(data);
fileWriter.flush();
fileWriter.close();
}
}
字符流输入流:
inputReader字符流的测试代码:
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
public class inputReader1 {
public static void main(String[] args) throws IOException {
FileReader fileReader = new FileReader("src/data1.txt");
int chars;
while ((chars=fileReader.read())!=-1){
System.out.println((char) chars);
}
}
}
六、文件输入输出流举例:
1.File类的list Files无参方法举例
Fail 类list fails无参方法。这个方法会返回一个file类的数组,它的作用是当一个file类的对象指向一个特定的路径。这个对象去调用list files无参方法时,将会返回file类的数组,这个数组里边的每一个元素将会指向一个特定的文件
import java.io.File;
import java.io.IOException;
import java.util.Date;
public class TestFile1 {
public static void main(String[] args) throws IOException {
File dir2=new File("D:/Workspaces");
File fileName2[]=dir2.listFiles();
File s=null;
for (int i = 0; i <fileName2.length ; i++) {
if (fileName2[i].getName().endsWith(".txt")){
if (s==null)
s=fileName2[i];
System.out.println(fileName2[i].getName());
}
}
System.out.println("Name:"+s.getName()+"\nParent:"+s.getParent()
+"\nPath:"+s.getPath()+"\nAbsolutePath?"+s.getAbsolutePath()+
"\nAbsolute?"+s.isAbsolute()+
"\nCan read:"+s.canRead()+
"\nCan write"+s.canWrite()+"\nExist:"+s.exists()+
"\nLength:"+s.length()+"\nLast Modified:"+
new Date(s.lastModified()));
s=new File("D:\\Workspaces\\a3.txt");
s.createNewFile();
}
}
2.文件字节流举例:
package IO;
import java.io.*;
import java.util.*;
//文件字节流为什么要用try catch一块呢?写文件流write方法,读文件流read方法,都会抛出输入输出异常,write和read方法在声明的时候都要抛出异常
public class zijieliu {
public static void main(String[] args) {
{
File f = new File("lianxi1.txt");
try {
FileOutputStream out = new FileOutputStream(f, true);
//构造方法中为file类的对象f,说明Out对象可以向F所指定的当前路径下面lianxi1.txt写文件
Scanner reader = new Scanner(System.in);
String s = "";
System.out.println("请输入内容:");
s = reader.nextLine();
//从键盘上通过reader对象调用next line 方法,输接收字符串
//Next line,它的特点是遇到回车即截止,遇到空格不截止,所以接收字符串里面可以包含空格,如果是next(),接受的字符串不允许有空格
while (!s.equals("finish"))//判断接收的字符串是否为finish,
{
byte[] c = s.getBytes();
out.write(c);
//将接收的字符串通过调用string类的方法getBytes把字符串解析成一个字节数组C,之后再通过文件字节输出流对象out,把C这个数组里面的内容写到指定的文件当中
out.write((int) '\r');//回车不换行
out.write((int) '\n');//\r\n回车换行
//int类型,将一个字符转换成在unicode表当中的位置,然后再将这个位置作为参数写到文件里,实际上是记下了这个字符所对应的位置
//调用了参数不同的两类write写方法,一个是写一批数据,另外一个是只写一个字符所对应的位置数据
s = reader.nextLine();
}
reader.close();
out.close();
FileInputStream in = new FileInputStream(f);//文件中有中文,读取回出错,调用read方法每次只能读取一个字节
int a;
while ((a = in.read()) != -1)//读取一个内容,返回这个字节所对应的整形值,然后把它赋给a,它返回的值和-1进行比较的时候,如果不等于-1,说明文件里面内容没有读完
{
System.out.print((char) a);
}
in.close();
} catch (IOException ioe) {
System.out.println("输入输出错误!");
}
}
}
}
3.文件字符流举例:
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Scanner;
public class TextFileRW {
public static void main(String[] args) {
File f=new File("Lianxi.txt");
try {
FileWriter out=new FileWriter(f,true);
Scanner reader = new Scanner(System.in);
String s="";
System.out.println("请输入内容");
s=reader.nextLine();
while (!s.equals("finish")){
out.write(s);
out.write((int)'\r');
out.write((int)'\n');
s= reader.nextLine();
}
reader.close();
out.close();
FileReader in = new FileReader(f);
int a;
while ((a=in.read())!=-1){
System.out.println((char)a);
}
in.close();
} catch (IOException ioe) {
System.out.println("输入输出错误");
}
}
}
补充:
1.IO 流的作用:
实现数据的输入和输出:通过 IO 流,可以从外部源中读取数据到程序中,或
者将程序中的数据写入到外部源中。
处理文件操作:可以通过 IO 流读取、写入文件,实现文件的读取、写入和操
作。
网络通信:通过 IO 流可以实现网络通信,包括建立 Socket 连接、传输数据等。
2. IO 流的使用场景:
文件操作:读取、写入和处理文件。
网络编程:建立 Socket 连接,进行网络通信。
数据处理:通过 IO 流实现数据的输入、输出和处理,包括序列化、反序列化
等操作。
图像处理:读取、写入图像文件,并进行图像处理操作。