Java中IO流不作为Socket基础,而是配合Socket承担数据读写职责:Socket是通信管道,InputStream/OutputStream是水流;需调用getInputStream()/getOutputStream()获取流对象,再通过字节流或转换流(如InputStreamReader)处理数据,NIO中则由SocketChannel与ByteBuffer替代。

Java 中 IO 流在网络编程中不是“作为 Socket 的基础”,而是与 Socket 配合使用,承担数据读写的具体职责。Socket 本身是通信连接的抽象(IP + 端口),它不直接处理数据内容;真正负责把字节从网络搬进内存、或把内存数据发到网络的,是基于 Socket 创建的 输入流和输出流。
Socket 与 IO 流的关系很明确:Socket 是管道,IO 流是水流
当你用 new Socket("localhost", 8080) 建立连接后,它本身不读也不写——你需要调用它的 getInputStream() 和 getOutputStream() 方法,拿到对应的流对象,才能开始收发数据。
Socket socket = new Socket("localhost", 8080);
InputStream in = socket.getInputStream(); // 从网络读字节
OutputStream out = socket.getOutputStream(); // 往网络写字节这两个流是阻塞式的字节流(BIO),底层直接绑定到操作系统 socket 文件描述符,每次 read() 或 write() 都可能触发系统调用。
字节流是网络 IO 的默认载体,字符流需转换
网络传输本质是字节(TCP/IP 协议栈只认 byte),所以 InputStream / OutputStream 是最自然的选择:
立即学习“Java免费学习笔记(深入)”;
-
socket.getInputStream()→InputStream -
socket.getOutputStream()→OutputStream
如果要处理文本(比如 HTTP 请求头、JSON 字符串),不能直接用 FileReader 这类文件字符流,而要用 转换流:
// 把字节流转成字符流,指定编码(避免乱码) Reader reader = new InputStreamReader(socket.getInputStream(), StandardCharsets.UTF_8); Writer writer = new OutputStreamWriter(socket.getOutputStream(), StandardCharsets.UTF_8);
这样就能用 read(char[])、write(String) 等更符合文本语义的方式操作,但底层仍是字节流动。
Java项目代码review工具。分析Git变更+完整调用链路上下文,推断业务需求,进行多维度评分和分类汇总,生成完整PRD文档。包含细粒度Java代码审查清单(Null安全、异常处理、Streams、并发、equals/hashCode、资源管理、API设计、性能、MyBatis/ORM、事务边界、SQL/DD...
实际交互中常搭配缓冲流提升性能
裸 InputStream 每次 read() 可能只读 1 字节,频繁系统调用开销大。真实项目中几乎总是包装一层缓冲:
BufferedInputStream bin = new BufferedInputStream(socket.getInputStream()); BufferedOutputStream bout = new BufferedOutputStream(socket.getOutputStream());
或者更常见的是结合 DataInputStream/DataOutputStream,支持读写 int、long、UTF 字符串等结构化数据:
DataInputStream din = new DataInputStream(new BufferedInputStream(socket.getInputStream()));
DataOutputStream dout = new DataOutputStream(new BufferedOutputStream(socket.getOutputStream()));
dout.writeUTF("Hello Server");
String resp = din.readUTF();注意:DataInputStream 和 DataOutputStream 必须配对使用,且协议需双方约定。
NIO 场景下,流被 Channel 替代,但逻辑相似
在 NIO(java.nio)中,不再用 InputStream/OutputStream,而是用:
-
SocketChannel+ByteBuffer+Selector - 通过
channel.read(buffer)和channel.write(buffer)完成收发
但它解决的是“一个线程管多个连接”的问题,数据单位仍是字节,只是调度模型变了。ByteBuffer 就是 NIO 里的“缓冲区版流”。
所以无论 BIO 还是 NIO,核心没变:网络通信的数据搬运工作,始终由面向字节的机制承担;IO 流(或 Channel)是实现这一搬运的标准化接口。
不复杂但容易忽略


















