第13天: Java I/O 流与文件操作全面解析

 概述

Java I/O(输入/输出)系统提供了强大的数据读写能力,是Java编程中处理数据输入输出的核心机制。本文将深入介绍Java I/O流的概念、分类、File类使用方法以及各种处理流的应用场景。

 一、I/O流基本概念

I/O流**是Java中处理输入输出的抽象概念:
- I (Input)**:输入,指数据从外部流向程序
- O (Output)**:输出,指数据从程序流向外部
- 流(Stream)**:像管道或通道,能够双向输送数据

 二、I/O流分类体系

Java I/O流可按不同维度进行分类:

 1. 按流向分
- 输入流:从数据源读取数据到程序
- 输出流:从程序写入数据到目的地

 2. 按处理单位分
- 字节流:以字节(8位)为单位处理数据,适合所有类型文件
- 字符流:以字符(16位)为单位处理数据,适合文本文件

 3. 按功能分
- 节点流:直接连接数据源的管道,没有任何额外功能
- 处理流:连接其他管道的管道,提供缓冲、转换等增强功能

 三、File类:文件与目录操作

Java遵循"万事万物皆对象"的理念,通过File类表示文件和目录路径名。

 基本文件操作示例

```java
public static void main(String[] args) throws IOException {
    File file = new File("E:\\dz18\\dz181.txt");
    
    System.out.println(file.getName());    // 文件名及后缀名: dz18.txt
    System.out.println(file.getPath());    // 文件地址: E:\dz18\dz18.txt
    System.out.println(file.length());     // 文件大小: 764
    System.out.println(file.canRead());    // 是否可读: true
    System.out.println(file.isFile());     // 是否为文件: true
    
    if(!file.exists()) {
        file.createNewFile(); // 创建文件
        System.out.println("文件创建成功");
    } else {
        file.delete(); // 删除文件
    }
}
```

 目录操作示例

```java
public static void main(String[] args) {
    File file = new File("E:\\dz18");
    
    if(!file.isFile()) { // 判断是否为文件夹
        if(file.exists()) { // 判断文件夹是否存在
            file.delete();
            System.out.println("删除");
        } else {
            file.mkdirs(); // 创建多层文件夹
            file.mkdir();  // 创建单层文件夹
            System.out.println("创建");
        }
    } else {
        System.out.println("是文件");
    }
    
    // 获取目录下所有子文件和子目录
    String[] list = file.list();
    for(String s : list) {
        System.out.println(s);
    }
}
```

 递归遍历目录结构

```java
// 模拟杀毒软件全盘扫描功能
public void getFileInfo(File file) {
    File[] files = file.listFiles(); // 获取目录下所有文件对象
    int count = 0;
    
    for(int i = 0; i < files.length; i++) {
        if(files[i].isFile()) {
            for(int j = 0; j <= count; j++) {
                System.out.print("\t");
            }
            System.out.println(files[i].getName());
        } else {
            System.out.println(files[i].getName());
            getFileInfo(files[i]); // 递归调用
            count++;
        }
    }
}

public static void main(String[] args) {
    File file = new File("D:\\盛世吉软\\1.java基础");
    new FileTest().getFileInfo(file);
}
```

 四、处理流详解

 1. 缓冲流(Buffered Stream)

自带缓冲区(默认大小8192字节),提高I/O效率:

```java
// 使用缓冲流复制文件
public static void main(String[] args) throws IOException {
    // 1. 获取数据源对象
    File eFile = new File("E:\\dz18\\dz18.txt");
    File cFile = new File("C:\\Users\\a\\Desktop\\dz18.txt");
    
    // 2. 获取管道流对象:先获得节点流,再获得处理流
    FileReader fr = new FileReader(eFile);
    BufferedReader br = new BufferedReader(fr);
    FileWriter fw = new FileWriter(cFile);
    BufferedWriter bw = new BufferedWriter(fw);
    
    // 3. 开始读写
    String str = br.readLine();
    int count = 0;
    while(str != null) {
        bw.write(str);
        bw.newLine();
        count++;
        str = br.readLine();
    }
    System.out.println(count + "行数据已复制");
    
    // 4. 关闭流资源:只需要关闭高级流
    bw.close(); // 自带刷新管道功能bw.flush()
    br.close();
}
```

 2. 转换流(Conversion Stream)

实现字节流与字符流之间的转换:

```java
// 使用转换流处理文件
public static void main(String[] args) throws IOException {
    // 1. 获取数据源对象
    File eFile = new File("E:\\dz18\\dz18.txt");
    File cFile = new File("C:\\Users\\a\\Desktop\\dz18.txt");
    
    // 2. 获取管道流对象
    FileInputStream fis = new FileInputStream(eFile);
    InputStreamReader isr = new InputStreamReader(fis);
    BufferedReader br = new BufferedReader(isr);
    
    FileOutputStream fos = new FileOutputStream(cFile);
    OutputStreamWriter osw = new OutputStreamWriter(fos);
    BufferedWriter bw = new BufferedWriter(osw);
    
    // 3. 开始读写
    String str = br.readLine();
    while(str != null) {
        bw.write(str);
        bw.newLine();
        str = br.readLine();
    }
    
    // 4. 关闭流资源
    bw.close();
    br.close();
    System.out.println("复制成功!");
}
```

 3. 数据流(Data Stream)

在传输数据的同时保存数据类型信息:

```java
public static void main(String[] args) throws IOException {
    // 1. 获取数据源对象
    File file = new File("E:\\dz18\\123.txt");
    
    // 2. 获取管道流对象
    FileOutputStream fos = new FileOutputStream(file);
    DataOutputStream dos = new DataOutputStream(fos);
    
    FileInputStream fis = new FileInputStream(file);
    DataInputStream dis = new DataInputStream(fis);
    
    // 3. 开始写入和读取(必须按相同顺序)
    dos.writeBoolean(true);
    dos.writeUTF("你好");
    dos.writeDouble(123.4);
    dos.writeInt(9);
    
    // 取出:必须按照写入的顺序
    if(dis.readBoolean()) {
        System.out.println("boolean值是true!");
    }
    System.out.println(dis.readUTF());
    System.out.println(dis.readDouble() * dis.readInt());
    
    // 4. 关闭流资源
    dis.close();
    dos.close();
}
```

 4. 对象流(Object Stream)

实现对象的序列化与反序列化:

```java
public static void main(String[] args) throws IOException, ClassNotFoundException {
    // 1. 获取数据源对象
    File file = new File("E:\\dz18\\obj.txt");
    
    // 2. 获取管道流对象
    FileOutputStream fos = new FileOutputStream(file);
    ObjectOutputStream oos = new ObjectOutputStream(fos);
    
    FileInputStream fis = new FileInputStream(file);
    ObjectInputStream ois = new ObjectInputStream(fis);
    
    // 3. 序列化与反序列化操作
    Person person = new Person("张三", 23, "123456");
    oos.writeObject(person);
    
    Object object = ois.readObject();
    if(object instanceof Person) {
        Person p = (Person) object;
        System.out.println(p.getId());
    }
    
    // 4. 关闭流资源
    ois.close();
    oos.close();
    System.out.println("存储成功!");
}
```

五、对象序列化注意事项

1. 实现Serializable接口:需要序列化的对象所属类必须实现此接口
2. 添加serialVersionUID:在反序列化时,JVM会比较字节流中的serialVersionUID与程序中相应实体类的serialVersionUID
   - ID值相同:进行反序列化操作
   - ID值不同:报错并停止反序列化,起到安全保护作用
3. transient修饰符:被transient修饰的属性不会被序列化
4. 嵌套对象序列化:被序列化的类的内部所有属性必须是可序列化的
   - 如果有其他类作为属性,这些类也必须实现Serializable接口并拥有serialVersionUID
5. 静态变量:序列化对静态变量无效
   - 静态变量被序列化时,所有对象实例将共享同一静态值
   - 反序列化时无法对应具体对象实例

 总结

Java I/O系统提供了丰富而强大的数据处理能力,从基本的文件操作到复杂的数据序列化,涵盖了各种应用场景。掌握这些核心概念和技术,能够帮助开发者高效处理各种数据输入输出需求,构建更加健壮的应用程序。理解流的分类体系、熟悉File类的使用方法以及掌握各种处理流的特性,是成为Java高级开发者的必备技能。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值