【JavaSE】IO集合全面梳理与核心操作详解

一、Java IO体系概述

Java IO(输入/输出)是Java处理数据输入输出的核心API,它提供了一套完整的机制来处理不同类型的数据源和数据流向。Java IO操作主要基于流(Stream) ​ 的概念,流可以看作是数据流动的通道,数据从源头(如文件、网络、内存等)流向目的地。 根据数据处理方式的不同,Java IO流主要分为两大类:

  • 字节流:以字节为单位进行数据读写,可以处理所有类型的数据
  • 字符流:以字符为单位进行数据读写,专门处理文本数据

二、IO流核心分类与体系结构

2.1 字节流体系

字节流是Java IO中最基础的流类型,主要用于处理二进制数据。 输入流(InputStream)继承体系

复制代码
InputStream(抽象类)
├── FileInputStream(文件输入流)
├── ByteArrayInputStream(字节数组输入流)
├── FilterInputStream(过滤输入流)
│   ├── BufferedInputStream(缓冲输入流)
│   ├── DataInputStream(数据输入流)
│   └── ObjectInputStream(对象输入流)
└── PipedInputStream(管道输入流)

输出流(OutputStream)继承体系

复制代码
OutputStream(抽象类)
├── FileOutputStream(文件输出流)
├── ByteArrayOutputStream(字节数组输出流)
├── FilterOutputStream(过滤输出流)
│   ├── BufferedOutputStream(缓冲输出流)
│   ├── DataOutputStream(数据输出流)
│   └── ObjectOutputStream(对象输出流)
└── PipedOutputStream(管道输出流)

2.2 字符流体系

字符流专门用于处理文本数据,支持字符编码转换。

读取流(Reader)继承体系

复制代码
Reader(抽象类)
├── InputStreamReader(字节字符转换流)
│   └── FileReader(文件读取流)
├── BufferedReader(缓冲读取流)
├── CharArrayReader(字符数组读取流)
└── StringReader(字符串读取流)

写入流(Writer)继承体系

复制代码
Writer(抽象类)
├── OutputStreamWriter(字符字节转换流)
│   └── FileWriter(文件写入流)
├── BufferedWriter(缓冲写入流)
├── CharArrayWriter(字符数组写入流)
├── StringWriter(字符串写入流)
└── PrintWriter(打印写入流)

三、文件操作与File类

File类是Java IO中用于表示文件和目录路径的抽象,它提供了丰富的文件操作方法。

3.1 File类基本操作

csharp 复制代码
import java.io.File;
import java.io.IOException;

public class FileOperationExample {
    public static void main(String[] args) {
        // 创建File对象
        File file = new File("example.txt");
        
        try {
            // 创建新文件
            if (file.createNewFile()) {
                System.out.println("文件创建成功: " + file.getName());
            } else {
                System.out.println("文件已存在");
            }
            
            // 文件信息获取
            System.out.println("文件路径: " + file.getPath());
            System.out.println("绝对路径: " + file.getAbsolutePath());
            System.out.println("文件大小: " + file.length() + " 字节");
            System.out.println("可读: " + file.canRead());
            System.out.println("可写: " + file.canWrite());
            
            // 删除文件
            if (file.delete()) {
                System.out.println("文件删除成功");
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

3.2 目录操作

arduino 复制代码
import java.io.File;

public class DirectoryExample {
    public static void main(String[] args) {
        // 创建目录
        File dir = new File("myDirectory");
        if (!dir.exists()) {
            if (dir.mkdir()) {
                System.out.println("目录创建成功");
            }
        }
        
        // 列出目录内容
        if (dir.isDirectory()) {
            String[] files = dir.list();
            System.out.println("目录内容:");
            for (String file : files) {
                System.out.println(file);
            }
        }
        
        // 创建多级目录
        File multiDir = new File("parent/child/grandchild");
        if (multiDir.mkdirs()) {
            System.out.println("多级目录创建成功");
        }
    }
}

四、字节流详细操作

4.1 文件字节流操作

java 复制代码
import java.io.*;

public class ByteStreamExample {
    
    // 文件写入示例
    public static void writeFile(String filename, String content) {
        try (FileOutputStream fos = new FileOutputStream(filename)) {
            byte[] contentBytes = content.getBytes();
            fos.write(contentBytes);
            System.out.println("文件写入成功");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    
    // 文件读取示例 - 单字节读取
    public static void readFileSingleByte(String filename) {
        try (FileInputStream fis = new FileInputStream(filename)) {
            int content;
            System.out.println("单字节读取内容:");
            while ((content = fis.read()) != -1) {
                System.out.print((char) content);
            }
            System.out.println();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    
    // 文件读取示例 - 字节数组读取
    public static void readFileByteArray(String filename) {
        try (FileInputStream fis = new FileInputStream(filename)) {
            byte[] buffer = new byte[1024];
            int bytesRead;
            StringBuilder content = new StringBuilder();
            
            while ((bytesRead = fis.read(buffer)) != -1) {
                content.append(new String(buffer, 0, bytesRead));
            }
            System.out.println("字节数组读取内容: " + content.toString());
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    
    public static void main(String[] args) {
        String filename = "test.txt";
        String content = "Hello, Java IO World!\n这是测试内容。";
        
        writeFile(filename, content);
        readFileSingleByte(filename);
        readFileByteArray(filename);
    }
}

4.2 缓冲字节流操作

缓冲流通过内置缓冲区显著提高IO效率。

java 复制代码
import java.io.*;

public class BufferedStreamExample {
    
    public static void copyFileWithBuffer(String source, String destination) {
        try (FileInputStream fis = new FileInputStream(source);
             BufferedInputStream bis = new BufferedInputStream(fis);
             FileOutputStream fos = new FileOutputStream(destination);
             BufferedOutputStream bos = new BufferedOutputStream(fos)) {
            
            byte[] buffer = new byte[4096];
            int bytesRead;
            
            while ((bytesRead = bis.read(buffer)) != -1) {
                bos.write(buffer, 0, bytesRead);
            }
            bos.flush(); // 确保所有数据写入
            System.out.println("文件复制完成");
            
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    
    public static void main(String[] args) {
        copyFileWithBuffer("source.txt", "destination.txt");
    }
}

五、字符流详细操作

5.1 文件字符流操作

字符流专门用于文本文件处理,支持字符编码。

java 复制代码
import java.io.*;

public class CharacterStreamExample {
    
    // 使用FileReader和FileWriter
    public static void copyTextFile(String source, String destination) {
        try (FileReader reader = new FileReader(source);
             FileWriter writer = new FileWriter(destination)) {
            
            int character;
            while ((character = reader.read()) != -1) {
                writer.write(character);
            }
            System.out.println("文本文件复制完成");
            
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    
    // 使用指定字符编码
    public static void readWithEncoding(String filename, String charset) {
        try (InputStreamReader isr = new InputStreamReader(
                new FileInputStream(filename), charset)) {
            
            int character;
            while ((character = isr.read()) != -1) {
                System.out.print((char) character);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    
    public static void main(String[] args) {
        copyTextFile("input.txt", "output.txt");
        readWithEncoding("input.txt", "UTF-8");
    }
}

5.2 缓冲字符流操作

缓冲字符流提供了行读取等便利方法。

typescript 复制代码
import java.io.*;

public class BufferedCharacterExample {
    
    public static void readFileLineByLine(String filename) {
        try (FileReader fr = new FileReader(filename);
             BufferedReader br = new BufferedReader(fr)) {
            
            String line;
            int lineNumber = 1;
            
            while ((line = br.readLine()) != null) {
                System.out.println("行 " + lineNumber + ": " + line);
                lineNumber++;
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    
    public static void writeToFileWithBuffer(String filename, String[] lines) {
        try (FileWriter fw = new FileWriter(filename);
             BufferedWriter bw = new BufferedWriter(fw)) {
            
            for (String line : lines) {
                bw.write(line);
                bw.newLine(); // 写入换行符
            }
            System.out.println("文件写入完成");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    
    public static void main(String[] args) {
        String[] content = {
            "第一行内容",
            "第二行内容", 
            "第三行内容"
        };
        
        writeToFileWithBuffer("buffered.txt", content);
        readFileLineByLine("buffered.txt");
    }
}

六、高级IO操作

6.1 对象序列化

序列化允许将对象转换为字节流进行存储或传输。

java 复制代码
import java.io.*;
import java.util.Date;

class User implements Serializable {
    private static final long serialVersionUID = 1L;
    private String name;
    private transient String password; // transient字段不序列化
    private Date createTime;
    
    public User(String name, String password) {
        this.name = name;
        this.password = password;
        this.createTime = new Date();
    }
    
    // getter和setter方法
    @Override
    public String toString() {
        return "User{name='" + name + "', createTime=" + createTime + "}";
    }
}

public class SerializationExample {
    
    public static void serializeObject(User user, String filename) {
        try (ObjectOutputStream oos = new ObjectOutputStream(
                new FileOutputStream(filename))) {
            oos.writeObject(user);
            System.out.println("对象序列化完成");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    
    public static User deserializeObject(String filename) {
        try (ObjectInputStream ois = new ObjectInputStream(
                new FileInputStream(filename))) {
            User user = (User) ois.readObject();
            System.out.println("对象反序列化完成");
            return user;
        } catch (IOException | ClassNotFoundException e) {
            e.printStackTrace();
            return null;
        }
    }
    
    public static void main(String[] args) {
        User user = new User("张三", "123456");
        serializeObject(user, "user.ser");
        
        User deserializedUser = deserializeObject("user.ser");
        if (deserializedUser != null) {
            System.out.println("反序列化结果: " + deserializedUser);
        }
    }
}

6.2 数据流操作

数据流用于读写基本数据类型。

java 复制代码
import java.io.*;

public class DataStreamExample {
    
    public static void writePrimitiveData(String filename) {
        try (DataOutputStream dos = new DataOutputStream(
                new FileOutputStream(filename))) {
            
            dos.writeInt(100);
            dos.writeDouble(3.14159);
            dos.writeBoolean(true);
            dos.writeUTF("Hello, DataStream!");
            
            System.out.println("基本数据类型写入完成");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    
    public static void readPrimitiveData(String filename) {
        try (DataInputStream dis = new DataInputStream(
                new FileInputStream(filename))) {
            
            int intValue = dis.readInt();
            double doubleValue = dis.readDouble();
            boolean booleanValue = dis.readBoolean();
            String stringValue = dis.readUTF();
            
            System.out.println("读取结果:");
            System.out.println("int: " + intValue);
            System.out.println("double: " + doubleValue);
            System.out.println("boolean: " + booleanValue);
            System.out.println("String: " + stringValue);
            
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    
    public static void main(String[] args) {
        writePrimitiveData("data.bin");
        readPrimitiveData("data.bin");
    }
}

七、NIO简介与比较

Java NIO(New IO)提供了更高效的IO处理方式:

7.1 传统IO vs NIO

特性 传统IO NIO
数据处理方式 流导向 缓冲区导向
阻塞模式 阻塞IO 非阻塞IO可选
选择器 不支持 支持
性能 连接数少时良好 连接数多时更优

7.2 基本NIO操作示例

typescript 复制代码
import java.nio.file.*;
import java.nio.charset.StandardCharsets;
import java.util.List;

public class NIOExample {
    
    public static void nioReadFile(String filename) {
        try {
            Path path = Paths.get(filename);
            List<String> lines = Files.readAllLines(path, StandardCharsets.UTF_8);
            
            System.out.println("NIO读取文件内容:");
            for (String line : lines) {
                System.out.println(line);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    
    public static void nioWriteFile(String filename, List<String> content) {
        try {
            Path path = Paths.get(filename);
            Files.write(path, content, StandardCharsets.UTF_8);
            System.out.println("NIO文件写入完成");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    
    public static void main(String[] args) {
        List<String> content = List.of("NIO第一行", "NIO第二行", "NIO第三行");
        nioWriteFile("nio_example.txt", content);
        nioReadFile("nio_example.txt");
    }
}

八、实践与性能优化

8.1 拷贝文件

使用try-with-resources确保资源正确关闭。

arduino 复制代码
import java.io.*;

public class BestPracticeExample {
    
    public static void copyFileBestPractice(String source, String destination) {
        // 使用try-with-resources自动关闭资源
        try (InputStream in = new FileInputStream(source);
             OutputStream out = new FileOutputStream(destination)) {
            
            byte[] buffer = new byte[8192]; // 8KB缓冲区
            int bytesRead;
            
            while ((bytesRead = in.read(buffer)) != -1) {
                out.write(buffer, 0, bytesRead);
            }
        } catch (IOException e) {
            System.err.println("文件操作失败: " + e.getMessage());
            // 适当的错误处理和日志记录
        }
    }
    
    public static void main(String[] args) {
        copyFileBestPractice("source.txt", "destination.txt");
    }
}

8.2 性能优化建议

  1. 使用缓冲流:对于频繁的读写操作,始终使用缓冲流
  2. 选择合适的缓冲区大小:通常8KB是比较理想的缓冲区大小
  3. 及时关闭资源:使用try-with-resources确保资源释放
  4. 选择合适的流类型:文本数据用字符流,二进制数据用字节流
  5. 考虑使用NIO:对于高性能要求的场景考虑使用NIO

9. 总结

Java IO提供了强大而灵活的数据处理能力,主要包括:

  1. 字节流用于处理所有类型的数据,特别是二进制数据
  2. 字符流专门用于文本处理,支持字符编码
  3. 缓冲流提高IO操作效率
  4. 对象序列化用于对象持久化
  5. NIO提供更高效的IO处理方案

掌握Java IO体系对于任何Java开发者都是必备技能,合理的IO操作能够显著提升应用程序的性能和稳定性。建议根据具体需求选择合适的IO类,并遵循最佳实践来编写健壮的IO代码。

相关推荐
鱼弦1 小时前
redis 什么情况会自动删除key
后端
ShaneD7711 小时前
BaseContext:如何在Service层“隔空取物”获取当前登录用户ID?
后端
ShaneD7712 小时前
解决idea错误提示:无法解析'表名'
后端
李拾叁的摸鱼日常2 小时前
从 Java 8 升级视角看Java 17 新特性详解
java·后端
淡定__0092 小时前
深入理解 .NET 中的依赖注入(DI):从原理到实战
后端
Ankkaya2 小时前
小白服务器踩坑(2)- 自动化部署
后端
回家路上绕了弯2 小时前
Vavr 工具实用指南:Java 函数式编程的高效落地方案
分布式·后端
开心就好20252 小时前
没有 Mac 怎么上架 iOS 应用 跨平台团队的可行交付方案分析
后端
aiopencode2 小时前
构建可靠的 iOS 日志导出体系,从真机日志到系统行为的多工具协同实践
后端