15-Java IO与网络编程:从文件读写到手写聊天室

📅 2026/7/16 18:31:16
15-Java IO与网络编程:从文件读写到手写聊天室
Java IO与网络编程从文件读写到手写聊天室开篇IO和网络是很多Java开发者的短板工作中读取配置文件、上传下载文件、调用第三方接口、写聊天功能都离不开IO和网络编程。但很多开发者只会用框架封装好的API一旦底层出问题就抓瞎。本文从文件IO讲到Socket网络编程最后手写一个简易聊天室。一、IO流是什么IO是Input输入和Output输出的缩写。Java中的IO流就是数据在程序和外部设备之间传输的通道。文件 ←——输入流—— 程序 ——输出流——→ 文件输入流把外部数据读入程序输出流把程序数据写出到外部。二、IO流的分类2.1 按方向分类型方向代表类输入流外部 → 程序InputStream、Reader输出流程序 → 外部OutputStream、Writer2.2 按数据单位分类型单位适合场景字节流8位字节图片、视频、二进制文件字符流16位字符文本文件【面试高频】字节流是所有流的根字符流底层也是字节流只是多了编解码过程。三、常用IO流速查IO流体系 ├── 字节流 │ ├── InputStream抽象基类 │ │ └── FileInputStream │ └── OutputStream抽象基类 │ └── FileOutputStream ├── 字符流 │ ├── Reader抽象基类 │ │ └── FileReader │ └── Writer抽象基类 │ └── FileWriter └── 缓冲流 ├── BufferedInputStream / BufferedOutputStream └── BufferedReader / BufferedWriter四、文件读写实战4.1 字节流复制文件publicstaticvoidcopyFile(Stringsrc,Stringdest)throwsIOException{try(InputStreamisnewFileInputStream(src);OutputStreamosnewFileOutputStream(dest)){byte[]buffernewbyte[1024];intlen;while((lenis.read(buffer))!-1){os.write(buffer,0,len);}}}try-with-resources会自动关闭流不用手动写close()。4.2 字符流读取文本publicstaticvoidreadText(Stringpath)throwsIOException{try(BufferedReaderreadernewBufferedReader(newFileReader(path))){Stringline;while((linereader.readLine())!null){System.out.println(line);}}}字符流适合读文本BufferedReader可以一行一行读效率更高。4.3 写入文本publicstaticvoidwriteText(Stringpath,Stringcontent)throwsIOException{try(BufferedWriterwriternewBufferedWriter(newFileWriter(path,true))){writer.write(content);writer.newLine();}}FileWriter(path, true)中的true表示追加模式。五、网络编程基础5.1 IP和端口IP地址网络中设备的唯一标识比如192.168.1.1端口一台设备上不同程序的标识范围0~65535两个程序通过网络通信需要知道对方的IP和端口。5.2 TCP和UDP协议特点适用场景TCP面向连接、可靠传输、按顺序到达文件传输、HTTP、聊天UDP无连接、不可靠、速度快视频直播、DNS、游戏【面试高频】TCP通过三次握手建立连接四次挥手断开连接。UDP不需要建立连接直接发数据。六、Socket编程实战6.1 Socket是什么Socket套接字是网络通信的端点。TCP通信中服务端创建ServerSocket监听端口客户端创建Socket连接服务端。6.2 服务端代码publicclassServer{publicstaticvoidmain(String[]args)throwsIOException{ServerSocketserverSocketnewServerSocket(9999);System.out.println(服务端启动等待连接...);SocketsocketserverSocket.accept();System.out.println(客户端已连接);BufferedReaderreadernewBufferedReader(newInputStreamReader(socket.getInputStream()));Stringmsgreader.readLine();System.out.println(收到消息msg);reader.close();socket.close();serverSocket.close();}}6.3 客户端代码publicclassClient{publicstaticvoidmain(String[]args)throwsIOException{SocketsocketnewSocket(127.0.0.1,9999);BufferedWriterwriternewBufferedWriter(newOutputStreamWriter(socket.getOutputStream()));writer.write(你好服务端);writer.newLine();writer.flush();writer.close();socket.close();}}七、手写简易聊天室上面的例子只能发一条消息。下面实现一个能持续对话的简易聊天室。7.1 服务端支持多客户端publicclassChatServer{publicstaticvoidmain(String[]args)throwsIOException{ServerSocketserverSocketnewServerSocket(9999);System.out.println(聊天室服务端启动...);while(true){SocketsocketserverSocket.accept();newThread(newClientHandler(socket)).start();}}}classClientHandlerimplementsRunnable{privateSocketsocket;publicClientHandler(Socketsocket){this.socketsocket;}Overridepublicvoidrun(){try(BufferedReaderreadernewBufferedReader(newInputStreamReader(socket.getInputStream()))){Stringmsg;while((msgreader.readLine())!null){System.out.println(收到msg);}}catch(IOExceptione){e.printStackTrace();}}}7.2 客户端publicclassChatClient{publicstaticvoidmain(String[]args)throwsIOException{SocketsocketnewSocket(127.0.0.1,9999);BufferedWriterwriternewBufferedWriter(newOutputStreamWriter(socket.getOutputStream()));BufferedReaderconsolenewBufferedReader(newInputStreamReader(System.in));Stringmsg;while(!(msgconsole.readLine()).equals(exit)){writer.write(msg);writer.newLine();writer.flush();}writer.close();socket.close();}}八、与框架的连接8.1 Spring Boot读取配置文件Value(${server.port})privateStringport;Spring Boot启动时会读取application.properties或application.yml底层就是IO流。8.2 文件上传下载Spring中文件上传本质上就是解析客户端通过HTTP发送过来的IO流PostMapping(/upload)publicStringupload(MultipartFilefile)throwsIOException{file.transferTo(newFile(/upload/file.getOriginalFilename()));return上传成功;}8.3 Tomcat处理网络请求Tomcat作为Web服务器底层就是Socket编程。它监听端口接收HTTP请求解析请求头、请求体再交给Servlet处理。【面试高频】理解Tomcat底层网络模型是学习Netty、WebFlux等高性能网络框架的基础。九、开发踩坑实录坑 1忘记关闭流FileInputStreamfisnewFileInputStream(a.txt);// 用完没关闭后果文件句柄不释放程序运行久了会报Too many open files。正确做法用try-with-resources自动关闭。坑 2字符流读取二进制文件ReaderreadernewFileReader(photo.jpg);后果图片会被当作字符解析数据损坏。正确做法二进制文件用字节流。坑 3写文件后没有flushwriter.write(hello);// 没调用 flush()后果数据可能还在缓冲区没有真正写入文件。正确做法写完后调用flush()或者在try-with-resources关闭时自动刷新。坑 4服务端只接收一个客户端SocketsocketserverSocket.accept();// 没有循环也没有开新线程后果一个客户端连接后其他客户端无法连接。正确做法用循环accept()每个客户端单独开一个线程处理。坑 5网络通信没处理编码newInputStreamReader(socket.getInputStream())// 默认编码后果中文可能乱码。正确做法指定编码new InputStreamReader(is, StandardCharsets.UTF_8)。十、面试速记卡10.1 核心概念速查概念一句话解释字节流以字节为单位读写适合二进制文件字符流以字符为单位读写适合文本文件缓冲流带缓冲区减少IO次数提高效率TCP面向连接、可靠传输UDP无连接、不可靠、速度快Socket网络通信端点ServerSocket服务端监听端口的套接字10.2 高频面试题字节流和字符流有什么区别为什么使用缓冲流try-with-resources的作用是什么TCP和UDP有什么区别Socket通信的基本流程是什么如何实现一个能处理多个客户端的服务端文件上传下载的底层原理是什么10.3 口诀总结字节流读二进制字符流读文本 缓冲流加效率try-with-resources关资源 TCP可靠要握手UDP快速不保证 ServerSocket来监听Socket两端通信 写完记得flush网络指定UTF-8十一、小结IO流是Java与外部世界交互的桥梁网络编程是两个程序之间通信的基础。掌握IO流的核心分类、Socket通信的基本流程再手写一个聊天室网络编程就算入门了。实际开发中虽然很少直接写Socket但理解底层原理对排查问题、学习框架非常有帮助。