目录
- Java IO 概述
- 流的基本概念
- 流的分类
- InputStream 和 OutputStream
- Reader 和 Writer
- 文件操作
- 缓冲流
- 对象流
- 序列化和反序列化
- 文件压缩与解压缩
- 常见问题与解决方法
- 总结
1. Java IO 概述
Java IO 流是Java平台提供的一个重要API,用于处理文件系统、网络通信等相关的输入输出操作。它抽象了数据传输操作的细节,为开发者提供了一系列便捷的方法。一旦学会使用Java IO流,开发者可以轻松处理字符、字节流,从而读写文件、网络传输数据等。
2. 流的基本概念
在Java中,流是字节顺序传输的抽象,它可以代表任何有实际数据传输的过程,比如读写文件、网络数据传输等。流抽象出来的一个好处就是,让数据传输变得一致和方便。
- 输入流 (InputStream/Reader):用于读取数据。
- 输出流 (OutputStream/Writer):用于写出数据。
3. 流的分类
按数据处理类型分类
字节流 (Byte Stream)
- InputStream/OutputStream
- 用于处理8-bit 字节数据。适合处理所有类型的I/O数据,比如图像、视频、音乐等。
字符流 (Character Stream)
- Reader/Writer
- 用于处理16-bit字符数据,适用于文本数据。
按数据流向分类
输入流 (Input Stream)
- 读取数据字节,如FileInputStream, ByteArrayInputStream等。
输出流 (Output Stream)
- 写入数据字节,如FileOutputStream, ByteArrayOutputStream等。
4. InputStream 和 OutputStream
这两个类是所有字节输入输出流的基类。
InputStream
下面是一些常用的子类:
- FileInputStream: 从文件中读取字节信息。
- ByteArrayInputStream: 从内存中的字节数组读取字节。
- FilterInputStream: 用于修饰其他输入流,提供额外功能的流。
示例代码
FileInputStream fis = null;
try {
fis = new FileInputStream("example.txt");
int data;
while ((data = fis.read()) != -1) {
System.out.print((char) data);
}
} catch (IOException ex) {
ex.printStackTrace();
} finally {
if (fis != null) {
try {
fis.close();
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
OutputStream
下面是一些常用的子类:
- FileOutputStream: 向文件写入字节数据。
- ByteArrayOutputStream: 向内存中的字节数组写入字节数据。
- FilterOutputStream: 用于修饰其他输出流,提供额外功能的流。
示例代码
FileOutputStream fos = null;
try {
fos = new FileOutputStream("output.txt");
String data = "Hello, Java IO!";
fos.write(data.getBytes());
} catch (IOException ex) {
ex.printStackTrace();
} finally {
if (fos != null) {
try {
fos.close();
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
5. Reader 和 Writer
这两个类是所有字符输入输出流的基类。
Reader
下面是一些常用的子类:
- FileReader: 从文件中读取字符信息。
- BufferedReader: 读取效率比较高,可以读取一行字符。
- InputStreamReader: 将字节输入流转换为字符输入流。
示例代码
BufferedReader br = null;
try {
br = new BufferedReader(new FileReader("example.txt"));
String line;
while ((line = br.readLine()) != null) {
System.out.println(line);
}
} catch (IOException ex) {
ex.printStackTrace();
} finally {
if (br != null) {
try {
br.close();
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
Writer
下面是一些常用的子类:
- FileWriter: 向文件写入字符数据。
- BufferedWriter: 提供高效的字符写入操作。
- OutputStreamWriter: 将字节输出流转换为字符输出流。
示例代码
BufferedWriter bw = null;
try {
bw = new BufferedWriter(new FileWriter("output.txt"));
bw.write("Hello, Java IO!");
} catch (IOException ex) {
ex.printStackTrace();
} finally {
if (bw != null) {
try {
bw.close();
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
6. 文件操作
文件读取
使用FileInputStream读取文件:
import java.io.FileInputStream;
import java.io.IOException;
public class Main {
public static void main(String[] args) {
FileInputStream fis = null;
try {
fis = new FileInputStream("example.txt");
int data;
while ((data = fis.read()) != -1) {
System.out.print((char) data);
}
} catch (IOException ex) {
ex.printStackTrace();
} finally {
if (fis != null) {
try {
fis.close();
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
}
}
使用BufferedReader读取文件:
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
public class Main {
public static void main(String[] args) {
BufferedReader br = null;
try {
br = new BufferedReader(new FileReader("example.txt"));
String line;
while ((line = br.readLine()) != null) {
System.out.println(line);
}
} catch (IOException ex) {
ex.printStackTrace();
} finally {
if (br != null) {
try {
br.close();
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
}
}
文件写入
使用FileOutputStream写入文件:
import java.io.FileOutputStream;
import java.io.IOException;
public class Main {
public static void main(String[] args) {
FileOutputStream fos = null;
try {
fos = new FileOutputStream("output.txt");
String data = "Hello, Java IO!";
fos.write(data.getBytes());
} catch (IOException ex) {
ex.printStackTrace();
} finally {
if (fos != null) {
try {
fos.close();
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
}
}
使用BufferedWriter写入文件:
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
public class Main {
public static void main(String[] args) {
BufferedWriter bw = null;
try {
bw = new BufferedWriter(new FileWriter("output.txt"));
bw.write("Hello, Java IO!");
} catch (IOException ex) {
ex.printStackTrace();
} finally {
if (bw != null) {
try {
bw.close();
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
}
}
7. 缓冲流
缓冲流用于提高IO操作的效率。缓冲输入流和输出流分别是:
- BufferedInputStream
- BufferedOutputStream
- BufferedReader
- BufferedWriter
示例代码
BufferedInputStream
import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.IOException;
public class Main {
public static void main(String[] args) {
BufferedInputStream bis = null;
try {
bis = new BufferedInputStream(new FileInputStream("example.txt"));
int data;
while ((data = bis.read()) != -1) {
System.out.print((char) data);
}
} catch (IOException ex) {
ex.printStackTrace();
} finally {
if (bis != null) {
try {
bis.close();
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
}
}
BufferedOutputStream
import java.io.BufferedOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
public class Main {
public static void main(String[] args) {
BufferedOutputStream bos = null;
try {
bos = new BufferedOutputStream(new FileOutputStream("output.txt"));
String data = "Hello, Buffered IO!";
bos.write(data.getBytes());
} catch (IOException ex) {
ex.printStackTrace();
} finally {
if (bos != null) {
try {
bos.close();
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
}
}
8. 对象流
Java提供了对象流来进行序列化和反序列化操作,通过ObjectInputStream和ObjectOutputStream实现。
示例代码
对象写入到文件
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
public class Main {
public static void main(String[] args) {
try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("object.dat"))) {
oos.writeObject("Hello, Object IO!");
oos.writeObject(new Person("John", 30));
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
class Person implements java.io.Serializable {
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
// getter and setter
}
从文件读取对象
import java.io.FileInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
public class Main {
public static void main(String[] args) {
try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream("object.dat"))) {
String message = (String) ois.readObject();
Person person = (Person) ois.readObject();
System.out.println("Message: " + message);
System.out.println("Person: " + person.getName() + ", " + person.getAge());
} catch (IOException | ClassNotFoundException ex) {
ex.printStackTrace();
}
}
}
// Person class remains the same
9. 序列化和反序列化
序列化
序列化是将对象的状态转换为字节流的过程,通过实现Serializable
接口来实现。
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
public class Main {
public static void main(String[] args) {
Person person = new Person("John", 30);
try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("person.dat"))) {
oos.writeObject(person);
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
class Person implements java.io.Serializable {
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
// getter and setter
}
反序列化
反序列化是将字节流转换为对象的过程。
import java.io.FileInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
public class Main {
public static void main(String[] args) {
try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream("person.dat"))) {
Person person = (Person) ois.readObject();
System.out.println("Person: " + person.getName() + ", " + person.getAge());
} catch (IOException | ClassNotFoundException ex) {
ex.printStackTrace();
}
}
}
// Person class remains the same
10. 文件压缩与解压缩
Java 提供了java.util.zip包来实现文件的压缩和解压缩。
压缩
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
public class Main {
public static void main(String[] args) {
try (FileOutputStream fos = new FileOutputStream("compressed.zip");
ZipOutputStream zos = new ZipOutputStream(fos)) {
addToZipFile("example.txt", zos);
} catch (IOException ex) {
ex.printStackTrace();
}
}
private static void addToZipFile(String fileName, ZipOutputStream zos) throws IOException {
try (FileInputStream fis = new FileInputStream(fileName)) {
ZipEntry zipEntry = new ZipEntry(fileName);
zos.putNextEntry(zipEntry);
byte[] bytes = new byte[1024];
int length;
while ((length = fis.read(bytes)) >= 0) {
zos.write(bytes, 0, length);
}
zos.closeEntry();
}
}
}
解压缩
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
public class Main {
public static void main(String[] args) {
try (FileInputStream fis = new FileInputStream("compressed.zip");
ZipInputStream zis = new ZipInputStream(fis)) {
ZipEntry zipEntry = zis.getNextEntry();
while (zipEntry != null) {
String fileName = zipEntry.getName();
try (FileOutputStream fos = new FileOutputStream(fileName)) {
byte[] bytes = new byte[1024];
int length;
while ((length = zis.read(bytes)) >= 0) {
fos.write(bytes, 0, length);
}
}
zipEntry = zis.getNextEntry();
}
zis.closeEntry();
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
11. 常见问题与解决方法
问题 1:文件找不到
确保文件路径正确且文件存在。
FileInputStream fis = new FileInputStream("path/to/file.txt");
问题 2:权限问题
确保有权限读写文件。
File file = new File("path/to/file.txt");
if (file.canRead() && file.canWrite()) {
// Read or write
}
问题 3:流未关闭
使用try-with-resources增强型语法,确保流关闭。
try (FileInputStream fis = new FileInputStream("example.txt")) {
// Read data
} catch (IOException ex) {
ex.printStackTrace();
}
12. 总结
Java IO流是一个非常强大和灵活的机制,可以处理各种类型的数据输入和输出。掌握其基本使用和高级用法,是每个Java开发者都应该具备的技能。通过这篇博客,我们详细介绍了Java IO流的基本概念、分类、常见操作和一些高级用法,希望能帮助你更好地理解和使用Java IO流。如果你有任何疑问或建议,请在评论区留言。