1.I/O流
- 按数据单位:字节流(InputStream/OutputStream)、字符流(Reader/Writer)
- I/O流是操作数据的读写
- 操作对象:文件、控制台、内存
2.字符流和字节流的区别和实现
维度 | 字节流(Byte Stream) | 字符流(Character Stream) |
---|---|---|
数据单位 | 字节(8 位) | 字符(16 位 Unicode) |
编码处理 | 不处理编码,需手动控制 | 自动处理编码转换 |
核心类 | InputStream 、OutputStream | Reader 、Writer |
适用场景 | 二进制数据(图片、视频、压缩包等) | 文本数据(.txt、配置文件等) |
优势 | 通用,可处理所有类型数据 | 处理文本更便捷,避免乱码 |
实现顺序:
- 明确使用字符流还是字节流
- 创建对应实现对象
- 创建读取变量
- 循环读
查看读取结果:
- 创建一个文件写入对象(eg、filewriter)
- 将之前读出来的变量(eg、buffer[ ])写入
try-with-resources方式:
// 字节流读图片
try (FileInputStream in = new FileInputStream("image.jpg");
FileOutputStream out = new FileOutputStream("copy.jpg")) {
byte[] buffer = new byte[1024];
int len;
while ((len = in.read(buffer)) != -1) {
out.write(buffer, 0, len); // 直接读写字节
}
} catch (IOException e) {
e.printStackTrace();
}
// 字符流读文本(自动处理编码)
try (FileReader reader = new FileReader("text.txt");
FileWriter writer = new FileWriter("copy.txt")) {
char[] buffer = new char[1024];
int len;
while ((len = reader.read(buffer)) != -1) {
writer.write(buffer, 0, len); // 直接读写字符
}
} catch (IOException e) {
e.printStackTrace();
}
注:这行代码可以在读取完后自动关闭文件,无需手动close()
try (FileInputStream in = new FileInputStream("image.jpg");
FileOutputStream out = new FileOutputStream("copy.jpg"))
传统方式:
public static void copyImage() {
FileInputStream in = null;
FileOutputStream out = null;
try {
// 创建流对象
in = new FileInputStream("image.jpg");
out = new FileOutputStream("copy.jpg");
byte[] buffer = new byte[1024];
int len;
while ((len = in.read(buffer)) != -1) {
out.write(buffer, 0, len);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
// 手动关闭输出流
if (out != null) {
try {
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
// 手动关闭输入流(通常后关闭输入流)
if (in != null) {
try {
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
// 字符流复制文本(传统close()方式)
public static void copyText() {
FileReader reader = null;
FileWriter writer = null;
try {
// 创建流对象
reader = new FileReader("text.txt");
writer = new FileWriter("copy.txt");
char[] buffer = new char[1024];
int len;
while ((len = reader.read(buffer)) != -1) {
writer.write(buffer, 0, len);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
// 手动关闭输出流
if (writer != null) {
try {
writer.close();
} catch (IOException e) {
e.printStackTrace();
}
}
// 手动关闭输入流
if (reader != null) {
try {
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
查看读取结果:
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
public class BufferToTextFile {
public static void main(String[] args) {
char[] buffer = // 假设这里是你的文本字符数组
try (FileWriter fw = new FileWriter(new File("temp.txt"))) {
fw.write(buffer);
fw.flush();
System.out.println("文本已保存为temp.txt,可以打开查看");
} catch (IOException e) {
e.printStackTrace();
}
}
}
3.常用流实现类
- 字节流:FileInputStream、FileOutputStream、BufferedInputStream、BufferedOutputStream
- 字符流:FileReader、FileWriter、BufferedReader(含readLine())、BufferedWriter
File和Buffered的核心区别在于是否使用缓冲区
- 转换流:InputStreamReader(字节流 → 字符流)、OutputStreamWriter(字节流转字符流,指定编码)
// 2. 创建转换流,指定编码
// 读取 InputStreamReader:将字节流转换为字符流,指定输入编码为GBK
isr = new InputStreamReader(fis, "GBK");
// OutputStreamWriter:将字符流转换为字节流,指定输出编码为UTF-8
osw = new OutputStreamWriter(fos, "UTF-8");
- 对象流:ObjectInputStream(序列化)、ObjectOutputStream(反序列化)
- 注:需实现Serializable接口
public static void main(String[] args) {
User user = new User("Alice", 25, "123456");
try (ObjectOutputStream oos = new ObjectOutputStream(
new FileOutputStream("user.ser"))) {
// 将对象序列化到文件
oos.writeObject(user);
System.out.println("对象序列化完成");
} catch (Exception e) {
e.printStackTrace();
}
}
public static main(String[] args) {
try (ObjectInputStream ois = new ObjectInputStream(
new FileInputStream("user.ser"))) {
// 从文件反序列化对象
User user = (User) ois.readObject();
System.out.println("反序列化得到的对象:" + user);
// 输出:User{name='Alice', age=25, password='null'}
// (password被transient修饰,未被序列化,因此恢复为null)
} catch (Exception e) {
e.printStackTrace();
}
}
4.文件操作
java.io.File类:
操作类型 | 方法 | 说明 |
---|---|---|
判断存在性 | exists() | 判断文件 / 目录是否存在,返回 boolean |
isFile() | 判断是否为文件 | |
isDirectory() | 判断是否为目录 | |
创建 | createNewFile() | 创建新文件(若不存在),返回 boolean (成功为 true ) |
mkdir() | 创建单级目录(若父目录不存在则失败),返回 boolean | |
mkdirs() | 创建多级目录(父目录不存在则自动创建),返回 boolean | |
删除 | delete() | 删除文件或空目录,返回 boolean (成功为 true ) |
deleteOnExit() | 程序退出时删除文件 / 目录(常用于临时文件清理) | |
其他常用 | getName() | 获取文件 / 目录名 |
getPath() | 获取路径字符串 | |
getAbsolutePath() | 获取绝对路径字符串 |
例子:
import java.io.File;
import java.io.IOException;
public class FileDemo {
public static void main(String[] args) {
// 定义文件和目录路径
File file = new File("test.txt");
File dir = new File("demo/subdir");
// 1. 判断是否存在
System.out.println("文件是否存在:" + file.exists());
System.out.println("是否为目录:" + dir.isDirectory());
// 2. 创建操作
try {
// 创建文件
if (file.createNewFile()) {
System.out.println("文件创建成功");
}
} catch (IOException e) {
e.printStackTrace();
}
// 创建多级目录
if (dir.mkdirs()) {
System.out.println("目录创建成功");
}
// 3. 删除操作
if (file.delete()) {
System.out.println("文件删除成功");
}
// 删除目录(需先确保目录为空)
File subDir = new File("demo/subdir");
File parentDir = new File("demo");
if (subDir.delete() && parentDir.delete()) {
System.out.println("目录删除成功");
}
}
}