当前位置: 首页 > news >正文

Java IO相关技术小结

Java IO(输入/输出)相关技术

一、Java IO基础概念

  1. 数据流方向

    • 输入流(InputStream/Reader):从数据源(文件、网络、内存)读取数据到程序。
    • 输出流(OutputStream/Writer):从程序写入数据到目标位置。
  2. 数据类型

    • 字节流(Byte Stream):以字节为单位处理数据(InputStream/OutputStream),适用于二进制文件(图片、视频)。
    • 字符流(Character Stream):以字符为单位处理数据(Reader/Writer),自动处理字符编码(如UTF-8),适用于文本文件。
  3. 缓冲机制

    • 缓冲流(BufferedStream):通过内存缓冲区减少IO操作次数,提升性能(如BufferedInputStream)。

二、传统IO(BIO,Blocking IO)

1. 核心类库
  • 字节流

    // 文件操作示例
    try (FileInputStream fis = new FileInputStream("input.txt");FileOutputStream fos = new FileOutputStream("output.txt")) {int data;while ((data = fis.read()) != -1) {fos.write(data);}
    } catch (IOException e) {e.printStackTrace();
    }
    
    • 常用类FileInputStreamFileOutputStreamByteArrayInputStreamDataInputStream
  • 字符流

    // 文本文件读写示例
    try (BufferedReader br = new BufferedReader(new FileReader("input.txt"));BufferedWriter bw = new BufferedWriter(new FileWriter("output.txt"))) {String line;while ((line = br.readLine()) != null) {bw.write(line);bw.newLine();}
    } catch (IOException e) {e.printStackTrace();
    }
    
    • 常用类FileReaderFileWriterBufferedReaderPrintWriter
2. 装饰器模式

Java IO通过装饰器模式组合功能(如BufferedInputStream包装FileInputStream):

InputStream is = new BufferedInputStream(new FileInputStream("data.bin"));
3. 典型应用场景
  • 简单文件读写(配置文件、日志)。
  • 网络通信(Socket输入输出)。

三、NIO(New IO,JDK 1.4引入)

1. 核心特性
  • 非阻塞IO:基于通道(Channel)和缓冲区(Buffer),支持单线程处理多个连接(Selector模式)。
  • 零拷贝(Zero-copy):直接在内核空间完成数据传输,减少用户空间与内核空间的切换。
2. 核心组件
  • Buffer
    用于与Channel交互的数据容器,支持ByteBufferCharBuffer等。

    ByteBuffer buffer = ByteBuffer.allocate(1024);  // 分配堆内存缓冲区
    buffer.put("Hello".getBytes());  // 写入数据
    buffer.flip();  // 切换为读模式
    while (buffer.hasRemaining()) {System.out.print((char) buffer.get());
    }
    
  • Channel
    双向数据通道,支持异步读写,如:

    // 文件Channel示例
    try (FileChannel channel = new FileInputStream("input.txt").getChannel()) {ByteBuffer buffer = ByteBuffer.allocate(1024);int bytesRead = channel.read(buffer);  // 从通道读取到缓冲区
    } catch (IOException e) {e.printStackTrace();
    }
    
  • Selector
    实现单线程管理多个通道的事件(连接就绪、可读、可写):

    Selector selector = Selector.open();
    channel.configureBlocking(false);  // 设置非阻塞模式
    channel.register(selector, SelectionKey.OP_READ);  // 注册读事件while (selector.select() > 0) {Set<SelectionKey> keys = selector.selectedKeys();Iterator<SelectionKey> it = keys.iterator();while (it.hasNext()) {SelectionKey key = it.next();if (key.isReadable()) {// 处理读事件}it.remove();}
    }
    
3. 应用场景
  • 高并发网络编程(如Netty框架基于NIO实现)。
  • 文件大文件处理(零拷贝提升性能)。

四、AIO(Asynchronous IO,JDK 7引入)

1. 核心特性
  • 异步非阻塞:基于回调或Future模式,IO操作完成后通知应用程序。
  • 真正的异步:由操作系统完成IO操作,应用程序无需等待。
2. 核心类库
  • AsynchronousFileChannel:异步文件操作。
  • AsynchronousSocketChannel:异步网络通信。
// 异步文件读取示例
AsynchronousFileChannel channel = AsynchronousFileChannel.open(Paths.get("data.txt"), StandardOpenOption.READ);
ByteBuffer buffer = ByteBuffer.allocate(1024);channel.read(buffer, 0, buffer, new CompletionHandler<Integer, ByteBuffer>() {@Overridepublic void completed(Integer result, ByteBuffer attachment) {System.out.println("Read " + result + " bytes");}@Overridepublic void failed(Throwable exc, ByteBuffer attachment) {exc.printStackTrace();}
});
3. 应用场景
  • 异步网络服务(如高性能服务器)。
  • 实时数据处理(如日志收集、消息队列)。

五、IO与NIO/AIO对比

特性BIO(传统IO)NIO(非阻塞IO)AIO(异步IO)
阻塞模式同步阻塞同步非阻塞异步非阻塞
核心组件流(Stream)通道(Channel)、缓冲区(Buffer)、选择器(Selector)异步通道(AsynchronousChannel)
线程模型一个连接一个线程一个线程处理多个连接线程池处理回调
适用场景连接数少且固定的场景连接数多但短操作的场景(如Web服务器)连接数多且长操作的场景(如文件传输)

六、典型应用场景

  1. 文件操作

    • 小文件读写:使用BufferedReader/BufferedWriter(字符流)。
    • 大文件读写:使用FileChannel+ByteBuffer(NIO零拷贝)。
  2. 网络编程

    • 低并发:传统Socket+InputStream/OutputStream
    • 高并发:NIO的Selector+SocketChannel(如Netty框架)。
    • 异步通信:AIO的AsynchronousSocketChannel(如JDK自带的AsynchronousServerSocketChannel)。
  3. 序列化与反序列化

    • 使用ObjectInputStream/ObjectOutputStream实现Java对象的序列化。

七、注意事项

  1. 资源管理

    • 使用try-with-resources语句自动关闭流,避免内存泄漏。
  2. 字符编码

    • 处理文本时显式指定编码(如new FileReader("file.txt", StandardCharsets.UTF_8)),避免乱码。
  3. 性能优化

    • 优先使用缓冲流(BufferedInputStream等)减少IO次数。
    • 大文件读写时使用NIO的FileChannel替代传统流。
  4. 异常处理

    • 捕获IOException及其子类,处理连接断开、文件不存在等异常。

八、相关框架与工具

  • Netty:基于NIO的高性能网络编程框架,广泛用于分布式系统通信。
  • Apache Commons IO:提供更简洁的IO操作工具类(如FileUtils)。
  • Google Guava:增强的IO工具类(如FilesByteStreams)。

通过合理选择IO技术(BIO/NIO/AIO)和工具类库,可显著提升Java应用的性能和可维护性。

常用类库及工具

一、文件与路径操作类库

1. java.nio.file包(JDK 7+)
  • 核心类

    • Path:表示文件或目录的路径(替代File类)。
    • Paths:工厂类,用于创建Path实例。
    • Files:工具类,提供文件操作静态方法(读写、复制、删除等)。
    // 示例:递归复制目录
    Path source = Paths.get("src");
    Path target = Paths.get("dst");
    Files.walk(source).forEach(sourcePath -> {try {Path targetPath = target.resolve(source.relativize(sourcePath));Files.copy(sourcePath, targetPath, StandardCopyOption.REPLACE_EXISTING);} catch (IOException e) {e.printStackTrace();}});
    
2. java.io.File(传统文件操作)
  • 常用方法
    File file = new File("example.txt");
    file.exists();        // 判断文件是否存在
    file.isDirectory();   // 是否为目录
    file.listFiles();     // 获取目录下的文件列表
    file.createNewFile(); // 创建新文件
    

二、序列化与反序列化

1. 标准Java序列化
  • 核心接口

    • Serializable:标记接口,实现该接口的类可被序列化。
    • Externalizable:自定义序列化逻辑(需实现writeExternal()readExternal()方法)。
    // 序列化示例
    try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("data.ser"))) {oos.writeObject(new User("Alice", 25));
    } catch (IOException e) {e.printStackTrace();
    }// 反序列化示例
    try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream("data.ser"))) {User user = (User) ois.readObject();
    } catch (IOException | ClassNotFoundException e) {e.printStackTrace();
    }
    
2. 第三方序列化库
  • JSON序列化:Jackson、Gson

    // Jackson示例
    ObjectMapper mapper = new ObjectMapper();
    User user = new User("Bob", 30);
    String json = mapper.writeValueAsString(user); // 对象转JSON
    User deserializedUser = mapper.readValue(json, User.class); // JSON转对象
    
  • 高性能序列化:Kryo、Protostuff(基于Protobuf)。

三、压缩与归档

1. java.util.zip
  • 常用类

    • ZipInputStream/ZipOutputStream:读写ZIP文件。
    • GZIPInputStream/GZIPOutputStream:读写GZIP压缩文件。
    // ZIP压缩示例
    try (ZipOutputStream zos = new ZipOutputStream(new FileOutputStream("archive.zip"))) {File file = new File("data.txt");zos.putNextEntry(new ZipEntry(file.getName()));try (FileInputStream fis = new FileInputStream(file)) {byte[] buffer = new byte[1024];int length;while ((length = fis.read(buffer)) > 0) {zos.write(buffer, 0, length);}}zos.closeEntry();
    } catch (IOException e) {e.printStackTrace();
    }
    
2. Apache Commons Compress
  • 支持更多格式:ZIP、TAR、BZIP2、7-Zip等。
    // TAR文件操作示例
    try (TarArchiveOutputStream taos = new TarArchiveOutputStream(new FileOutputStream("archive.tar"))) {TarArchiveEntry entry = new TarArchiveEntry(new File("data.txt"));taos.putArchiveEntry(entry);try (FileInputStream fis = new FileInputStream("data.txt")) {IOUtils.copy(fis, taos);}taos.closeArchiveEntry();
    } catch (IOException e) {e.printStackTrace();
    }
    

四、网络编程类库

1. 标准Socket编程
  • TCP通信Socket(客户端)和ServerSocket(服务器)。

    // 服务器端示例
    try (ServerSocket serverSocket = new ServerSocket(8080)) {Socket clientSocket = serverSocket.accept();try (BufferedReader in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));PrintWriter out = new PrintWriter(clientSocket.getOutputStream(), true)) {String inputLine;while ((inputLine = in.readLine()) != null) {out.println("Server received: " + inputLine);}}
    } catch (IOException e) {e.printStackTrace();
    }
    
  • UDP通信DatagramSocketDatagramPacket

2. HTTP客户端
  • JDK 11+ HttpClient(替代HttpURLConnection):

    HttpClient client = HttpClient.newBuilder().build();
    HttpRequest request = HttpRequest.newBuilder().uri(URI.create("https://api.example.com/data")).GET().build();
    HttpResponse<String> response = client.send(request, BodyHandlers.ofString());
    System.out.println(response.body());
    
  • Apache HttpClient:功能更丰富,支持连接池、代理等。

五、管道与内存流

1. 管道流(Piped Streams)
  • 实现线程间通信:
    // 发送线程
    PipedOutputStream pos = new PipedOutputStream();
    writerThread = new Thread(() -> {pos.write("Hello, Pipe!".getBytes());pos.close();
    });// 接收线程
    PipedInputStream pis = new PipedInputStream(pos);
    readerThread = new Thread(() -> {int data;while ((data = pis.read()) != -1) {System.out.print((char) data);}pis.close();
    });
    
2. 内存流
  • ByteArrayInputStream/ByteArrayOutputStream:在内存中读写数据。
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    baos.write("Hello, Memory!".getBytes());
    byte[] bytes = baos.toByteArray();ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
    int data;
    while ((data = bais.read()) != -1) {System.out.print((char) data);
    }
    

六、字符编码转换

1. java.nio.charset
  • 常用类

    • Charset:表示字符集(如UTF-8、GBK)。
    • CharsetEncoder/CharsetDecoder:实现字符与字节的转换。
    // 字符串编码转换示例
    String text = "你好,世界";
    Charset utf8 = Charset.forName("UTF-8");
    Charset gbk = Charset.forName("GBK");ByteBuffer utf8Bytes = utf8.encode(text);
    CharBuffer gbkChars = gbk.decode(utf8Bytes);
    String convertedText = gbkChars.toString();
    

七、第三方工具类库

1. Apache Commons IO
  • 常用工具类

    • FileUtils:文件操作(读取、写入、复制)。
    • IOUtils:流操作(关闭、复制、转换为字符串)。
    // 示例:读取文件内容为字符串
    String content = FileUtils.readFileToString(new File("data.txt"), StandardCharsets.UTF_8);// 示例:复制输入流到输出流
    IOUtils.copy(inputStream, outputStream);
    
2. Google Guava
  • 核心类

    • Files:文件操作(读取、写入、临时文件)。
    • ByteStreams/CharStreams:字节流/字符流操作。
    // 示例:写入字符串到文件
    Files.asCharSink(new File("output.txt"), StandardCharsets.UTF_8).write("Hello, Guava!");// 示例:读取文件所有行
    List<String> lines = Files.asCharSource(new File("input.txt"), StandardCharsets.UTF_8).readLines();
    

八、NIO.2(JDK 7+)增强功能

1. 异步文件操作
  • AsynchronousFileChannel支持回调或Future模式:
    AsynchronousFileChannel channel = AsynchronousFileChannel.open(Paths.get("data.txt"), StandardOpenOption.READ);
    ByteBuffer buffer = ByteBuffer.allocate(1024);Future<Integer> result = channel.read(buffer, 0);
    while (!result.isDone()) {// 处理其他任务
    }
    int bytesRead = result.get();
    
2. 文件监听(WatchService)
  • 监控文件系统变化(创建、修改、删除):
    WatchService watcher = FileSystems.getDefault().newWatchService();
    Path dir = Paths.get(".");
    dir.register(watcher, StandardWatchEventKinds.ENTRY_CREATE,StandardWatchEventKinds.ENTRY_MODIFY);WatchKey key;
    while ((key = watcher.take()) != null) {for (WatchEvent<?> event : key.pollEvents()) {System.out.println("Event kind:" + event.kind() + " Path : " + event.context());}key.reset();
    }
    

九、总结

Java IO体系涵盖传统BIO、NIO、AIO及多种工具类库,选择时需根据场景权衡:

  • 简单文件操作:优先使用java.nio.file.Files或Apache Commons IO。
  • 网络编程:低并发用Socket,高并发用Netty(基于NIO)。
  • 序列化:标准场景用Java序列化,高性能场景用Kryo或Protobuf。
  • 压缩:ZIP/GZIP用JDK原生类,复杂格式用Apache Commons Compress。

合理结合JDK原生类库与第三方工具,可大幅提升IO操作的效率和代码简洁性。

序列化类库

一、Java原生序列化(JDK内置)

1. 实现步骤
  1. 让类实现Serializable接口(标记接口,无需实现方法)。
  2. 使用ObjectOutputStream序列化对象
  3. 使用ObjectInputStream反序列化对象
2. 示例代码
import java.io.*;// 1. 定义可序列化的类
class User implements Serializable {private static final long serialVersionUID = 1L; // 序列化版本号private String name;private int age;// transient字段不会被序列化private transient String password;public User(String name, int age, String password) {this.name = name;this.age = age;this.password = password;}// Getters and setterspublic String getName() { return name; }public int getAge() { return age; }public String getPassword() { return password; }
}public class SerializationExample {public static void main(String[] args) {User user = new User("Alice", 30, "securePass");// 2. 序列化对象到文件try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("user.ser"))) {oos.writeObject(user);System.out.println("对象已序列化");} catch (IOException e) {e.printStackTrace();}// 3. 从文件反序列化对象try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream("user.ser"))) {User deserializedUser = (User) ois.readObject();System.out.println("反序列化结果:");System.out.println("Name: " + deserializedUser.getName());System.out.println("Age: " + deserializedUser.getAge());System.out.println("Password: " + deserializedUser.getPassword()); // null(transient字段未被序列化)} catch (IOException | ClassNotFoundException e) {e.printStackTrace();}}
}
3. 关键特性
  • serialVersionUID:版本控制,建议显式声明以避免反序列化时的InvalidClassException
  • transient关键字:标记不需要序列化的字段(如密码、临时数据)。
  • 自动处理引用关系:若对象包含其他对象的引用,这些对象也需实现Serializable

二、JSON序列化(Jackson/Gson)

1. Jackson示例(需添加依赖)
<dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-databind</artifactId><version>2.14.2</version>
</dependency>
import com.fasterxml.jackson.databind.ObjectMapper;public class JacksonExample {public static void main(String[] args) throws Exception {User user = new User("Bob", 25, "pass123");ObjectMapper mapper = new ObjectMapper();// 1. 对象转JSON字符串String json = mapper.writeValueAsString(user);System.out.println("JSON: " + json);// 2. JSON字符串转对象User deserializedUser = mapper.readValue(json, User.class);System.out.println("Name: " + deserializedUser.getName());}
}
2. Gson示例(需添加依赖)
<dependency><groupId>com.google.code.gson</groupId><artifactId>gson</artifactId><version>2.10.1</version>
</dependency>
import com.google.gson.Gson;public class GsonExample {public static void main(String[] args) {User user = new User("Charlie", 35, "secure123");Gson gson = new Gson();// 1. 对象转JSONString json = gson.toJson(user);System.out.println("JSON: " + json);// 2. JSON转对象User deserializedUser = gson.fromJson(json, User.class);System.out.println("Age: " + deserializedUser.getAge());}
}

三、高性能序列化(Kryo)

1. 添加依赖
<dependency><groupId>com.esotericsoftware</groupId><artifactId>kryo</artifactId><version>5.4.0</version>
</dependency>
2. 示例代码
import com.esotericsoftware.kryo.Kryo;
import com.esotericsoftware.kryo.io.Input;
import com.esotericsoftware.kryo.io.Output;import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;public class KryoExample {public static void main(String[] args) {User user = new User("David", 40, "kryoPass");Kryo kryo = new Kryo();kryo.register(User.class);// 1. 序列化try (Output output = new Output(new FileOutputStream("user.kryo"))) {kryo.writeObject(output, user);System.out.println("Kryo序列化完成");} catch (IOException e) {e.printStackTrace();}// 2. 反序列化try (Input input = new Input(new FileInputStream("user.kryo"))) {User deserializedUser = kryo.readObject(input, User.class);System.out.println("Name: " + deserializedUser.getName());} catch (IOException e) {e.printStackTrace();}}
}

四、Protobuf(Google Protocol Buffers)

1. 添加依赖
<dependency><groupId>com.google.protobuf</groupId><artifactId>protobuf-java</artifactId><version>3.23.4</version>
</dependency>
2. 定义.proto文件
syntax = "proto3";package example;message User {string name = 1;int32 age = 2;string password = 3;
}
3. 生成Java类并使用
import com.google.protobuf.InvalidProtocolBufferException;public class ProtobufExample {public static void main(String[] args) {// 1. 创建对象并序列化UserProto.User user = UserProto.User.newBuilder().setName("Eve").setAge(28).setPassword("protoPass").build();byte[] bytes = user.toByteArray();// 2. 反序列化try {UserProto.User deserializedUser = UserProto.User.parseFrom(bytes);System.out.println("Age: " + deserializedUser.getAge());} catch (InvalidProtocolBufferException e) {e.printStackTrace();}}
}

五、对比与选择建议

序列化方式优点缺点适用场景
Java原生无需额外依赖,支持复杂对象结构性能较差,字节码大,兼容性差简单内部系统,对象结构稳定
JSON(Jackson)可读性强,跨语言支持,灵活性能一般,字节码较大前后端交互,REST API
Kryo高性能,字节码小不跨语言,需注册类内部系统高性能场景(如缓存)
Protobuf极致性能,跨语言,强兼容性需要编写.proto文件,学习成本较高分布式系统,微服务间通信

六、注意事项

  1. 版本兼容性:Java原生序列化需通过serialVersionUID控制版本。
  2. 安全性:避免反序列化不可信来源的数据(可能导致代码注入攻击)。
  3. 性能优化:对性能敏感的场景,优先选择Kryo或Protobuf。
  4. 字段控制:使用transient或Jackson的@JsonIgnore排除不需要序列化的字段。

根据场景选择合适的序列化方式,可显著提升系统的性能和可维护性。

http://www.dtcms.com/a/267232.html

相关文章:

  • SpringCloud系列(51)--SpringCloud Stream之使用分组解决消息重复消费问题
  • 你的Prompt还有很大提升
  • PyTorch中 item()、tolist()使用详解和实战示例
  • 企业微信iPad协议端强制拉群漏洞深度分析
  • Scrapy进阶封装(第四阶段:中间件设置,动态UA,ip代理池)
  • 【STM32实践篇】:GPIO 详解
  • 【深度学习新浪潮】基于扩散模型的图像编辑加速方法
  • 传输层 udptcp
  • 【性能优化与架构调优(二)】高性能数据库设计与优化
  • 【科普】Keil5软件使用教程、小技巧学习笔记:11个知识点。DIY机器人工房
  • 【数据结构】排序算法:归并与堆
  • Python入门Day4
  • Cortex-M 异常处理的 C 实现、栈帧以及 EXC_RETURN
  • 操作符详解(上)
  • 深入解析Redis 7.0中每种数据类型的底层实现
  • 【Qt】QStringLiteral 介绍
  • 2025最新Telegram快读助手:一款智能Telegram链接摘要机器人
  • 深入理解微服务中的服务注册与发现
  • 《Java修仙传:从凡胎到码帝》第四章:设计模式破万法
  • 云原生微服务间的异步消息通信:最终一致性与系统容错的架构实战
  • 供应链管理学习笔记4-供应链网络设计
  • 前端-CSS-day1
  • QT中的网络通信
  • LLM:位置编码详解与实现
  • 深层神经网络:原理与传播机制详解
  • java的注解和反射
  • JVM的位置和JVM的结构体系
  • 交互式剖腹产手术模拟系统开发方案
  • 【openp2p】学习3:【专利分析】一种基于混合网络的自适应切换方法、装 置、设备及介质
  • C# 事件(事件访问器)