Java IO流操作:文件读写与序列化实战


一、Java IO体系全景解析(含NIO对比)

1. IO流分类与核心类库

IO流
字节流
字符流
InputStream/OutputStream
Reader/Writer
FileInputStream
BufferedInputStream
FileReader
BufferedReader

2. 传统IO vs NIO核心差异

特性传统IONIO (New I/O)
数据单位流(Stream)块(Buffer)
阻塞模式同步阻塞同步非阻塞/异步
多路复用不支持Selector机制
适用场景低并发小文件高并发大文件

二、文件读写全场景实战

1. JDK 7+ Files API最佳实践

// 读取小文件(<1GB)  
String content = Files.readString(Path.of("data.txt"));  

// 写入文件(自动创建目录)  
Path dir = Path.of("logs/2023");  
Files.createDirectories(dir);  
Files.write(dir.resolve("app.log"), data.getBytes());  

// 大文件逐行处理(内存优化)  
try (Stream<String> lines = Files.lines(Path.of("bigfile.txt"))) {  
    lines.filter(line -> !line.isEmpty())  
         .forEach(System.out::println);  
}  

2. 高效缓冲流使用技巧

// 默认缓冲区8KB,大文件可调整  
try (BufferedReader reader = new BufferedReader(  
        new FileReader("data.txt"), 32768)) {  // 32KB缓冲区  
    String line;  
    while ((line = reader.readLine()) != null) {  
        // 处理逻辑  
    }  
}  

三、序列化与反序列化深度剖析

1. 默认序列化机制与陷阱

public class User implements Serializable {  
    private static final long serialVersionUID = 1L;  // 必须显式声明  
    private String name;  
    private transient String password;  // 敏感字段不序列化  

    // 自定义序列化逻辑  
    private void writeObject(ObjectOutputStream oos) throws IOException {  
        oos.defaultWriteObject();  
        oos.writeObject(EncryptUtil.encrypt(password));  
    }  

    private void readObject(ObjectInputStream ois) throws ClassNotFoundException, IOException {  
        ois.defaultReadObject();  
        this.password = EncryptUtil.decrypt((String) ois.readObject());  
    }  
}  

2. 安全序列化替代方案

方案优点缺点
JSON(Jackson)跨语言、可读性强性能低于二进制
Protobuf高性能、强类型需预定义Schema
Kryo极速序列化兼容性较差

四、NIO核心组件实战应用

1. Buffer状态机模型

ByteBuffer buffer = ByteBuffer.allocateDirect(1024);  // 堆外内存  
buffer.put("Hello".getBytes());  
buffer.flip();  // 切换读模式  
while (buffer.hasRemaining()) {  
    System.out.print((char) buffer.get());  
}  
buffer.clear();  // 重置缓冲区  

2. 多路复用Selector实现高并发

Selector selector = Selector.open();  
ServerSocketChannel ssc = ServerSocketChannel.open();  
ssc.bind(new InetSocketAddress(8080));  
ssc.configureBlocking(false);  
ssc.register(selector, SelectionKey.OP_ACCEPT);  

while (true) {  
    int readyChannels = selector.select();  
    if (readyChannels == 0) continue;  

    Set<SelectionKey> keys = selector.selectedKeys();  
    Iterator<SelectionKey> iter = keys.iterator();  
    while (iter.hasNext()) {  
        SelectionKey key = iter.next();  
        if (key.isAcceptable()) {  
            // 处理新连接  
        } else if (key.isReadable()) {  
            // 读取数据  
        }  
        iter.remove();  
    }  
}  

五、性能优化与资源管理

1. 内存映射文件(MappedByteBuffer)

try (RandomAccessFile file = new RandomAccessFile("data.bin", "rw")) {  
    MappedByteBuffer buffer = file.getChannel().map(  
        FileChannel.MapMode.READ_WRITE, 0, file.length());  
    buffer.putInt(128);  // 直接修改文件内容  
}  

2. 资源泄露检测与防范

错误模式

FileInputStream fis = new FileInputStream("file.txt");  
// 忘记关闭流 → 文件句柄泄露  

正确模式

try (InputStream is = new FileInputStream("file.txt");  
     OutputStream os = new FileOutputStream("copy.txt")) {  
    byte[] buffer = new byte[8192];  
    int len;  
    while ((len = is.read(buffer)) != -1) {  
        os.write(buffer, 0, len);  
    }  
}  // 自动关闭资源  

六、企业级实战案例

1. 实时日志采集系统(NIO实现)

public class LogTailer implements Runnable {  
    private final Path logPath;  
    private WatchService watchService;  

    public void run() {  
        try {  
            watchService = FileSystems.getDefault().newWatchService();  
            logPath.getParent().register(watchService,  
                StandardWatchEventKinds.ENTRY_MODIFY);  

            while (!Thread.interrupted()) {  
                WatchKey key = watchService.take();  
                for (WatchEvent<?> event : key.pollEvents()) {  
                    if (event.context().equals(logPath.getFileName())) {  
                        // 读取新增日志内容  
                        readNewLines();  
                    }  
                }  
                key.reset();  
            }  
        } catch (IOException | InterruptedException e) {  
            Thread.currentThread().interrupt();  
        }  
    }  
}  

2. 分布式对象传输(Protobuf集成)

// user.proto  
syntax = "proto3";  
message User {  
    string name = 1;  
    int32 age = 2;  
    repeated string tags = 3;  
}  
// Java序列化  
UserProto.User user = UserProto.User.newBuilder()  
    .setName("John").setAge(30).addTags("VIP").build();  
byte[] data = user.toByteArray();  

// 网络传输...  
UserProto.User parsedUser = UserProto.User.parseFrom(data);  

七、跨语言IO操作对比(Java vs Python vs Go)

功能JavaPythonGo
内存映射文件MappedByteBuffermmap模块syscall.Mmap
异步IOCompletableFuture/NIO.2asynciogoroutine + channel
序列化性能中等(需优化)慢(Pickle)快(Gob/Protobuf)
文件监控WatchServicewatchdogfsnotify库

八、常见陷阱与高频面试题

1. 乱码问题终极解决方案

// 指定字符集读取文件  
Files.readString(path, StandardCharsets.UTF_8);  

// 转换流处理编码  
new InputStreamReader(new FileInputStream("data.txt"), "GBK");  

2. 面试题:Java中有几种IO模型?

答案

  • 同步阻塞IO(BIO)
  • 同步非阻塞IO(NIO)
  • 多路复用IO(Selector)
  • 信号驱动IO(Unix特有)
  • 异步IO(AIO,Windows实现成熟)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值