# 学习目标
# 网络编程概念
# 网络编程概念
什么是网络编程编:写在不同计算机上进行数据传输的程序。
网络编程场景:网络应用程序、即时通信、网游对战、金融证券、国际贸易、邮件等等。
常见的软件架构有如下 2 种形式:Client-Server(CS) 、 Browser/Server(BS)Client-Server(CS): 客户端-服务端模式
# 网络编程三要素-IP 地址
你女朋友叫你去酒店找她学英语,你需要知道哪些信息?
- 酒店的地址
- 房间号
- 交流用的语言
我们要想在不同计算机之间传输数据必须具备 3 个条件,称为网络编程三要素:
- IP 地址
- 端口号
- 协议
IP 地址概念:互联网协议地址(Internet Protocol Address),俗称 IP。IP 地址用来给网络中的计算机进行编号。
IP 地址作用:通过 IP 地址可以找到网络中的某台电脑,IP 地址就相当于生活中的家庭住址。
IPv4:是一个 32 位的二进制数,通常被分为 4 个字节,表示成 a.b.c.d 的形式,例如 192.168.65.100。其中 a、b、c、d 都是 0~255 之间的十进制整数,那么最多可以表示 42 亿个。
IPv6:由于互联网的蓬勃发展,IP 地址的需求量愈来愈大,但是网络地址资源有限,使得 IP 的分配越发紧张。有资料显示,全球 IPv4 地址在 2011 年 2 月分配完毕。为了扩大地址空间,拟通过 IPv6 重新定义地址空间,采用 128 位地址长度,分成 8 组以十六进制数显示,表示成 ABCD:EF01:2345:6789:ABCD:EF01:2345:6789,号称可以为全世界的每一粒沙子编上一个网址,这样就解决了网络地址资源数量不够的问题。
查看本机 IP 地址,在 DOS 命令行输入: ipconfig
检查网络是否连通在 DOS 命令行输入: ping IP 地址/域名
特殊 IP 地址 127.0.0.1:是回送地址也称本地回环地址,可以代表本机的 IP 地址,一般用来测试使用
# 网络编程三要素-端口
端口介绍:我们一台电脑上会安装很多的应用程序,内网通,微信,QQ。如何找到计算机中的某个程序?应用程序在设备中唯一的标识。
端口作用:通过端口号可以找到电脑上的某个程序
用两个字节表示的整数,它的取值范围是 0~65535。其中 0~1023 之间的端口号用于一些知名的网络服务或者应用。我们自己使用 1024 以上的端口号就可以了。
# 网络编程三要素-协议
计算机网络中,连接和通信的规则被称为网络通信协议。
网络通信协议有两套参考模型:
- OSI 参考模型:世界互联协议标准,全球通信规范,单模型过于理想化,未能在因特网上进行广泛推广。
- TCP/IP 参考模型(或 TCP/IP 协议):事实上的国际标准。
OSI 参考模型 TCP/IP 参考模型 TCP/IP 参考模型各层对应协议 面向哪些 应用层 应用层 HTTP、FTP、Telnet、 DNS… 一般是应用程序需要关注的。
如浏览器,邮箱。程序员一般在这一层开发表示层 会话层 传输层 传输层 TCP、UDP、… 选择传输使用的 TCP , UDP 协议 网络层 网络层 IP、ICMP、ARP… 封装自己的 IP,对方的 IP 等信息 数据链路层 物理+数据链路层 硬件设备。010100101010100101010… 转换成二进制利用物理设备传输 物理层
UDP 协议特点: 用户数据报协议(User Datagram Protocol)
- 不需要连接
- 速度快
- 有大小限制一次最多发送 64K
- 易丢失数据
UDP 协议通信场景(速度要求高,数据完整性要求不高):
- 直播
- 语音通话
- 视频会话
TCP 协议特点: 传输控制协议 (Transmission Control Protocol)
- 需要连接
- 速度慢
- 没有大小限制
- 不易丢失数据
TCP 协议通信场景(速度要求不高,数据完整性要求高):
# UDP 通信程序
# 介绍 UDP 通信流程
UDP 协议通信是不需要连接的,相当于我们生活中的寄快递,直接寄出即可。
DatagramPacket: 表示数据包 数据的目的地 IP 地址 数据目的地端口号 DatagramPacket(byte[] buf, int offset, int length, InetAddress address, int port) 创建发送的数据包 DatagramPacket(byte[] buf, int length) 创建接收的数据包
发送端:1.创建发送端 2.创建一个数据包 3.发送数据包
接收端:1.创建接收端 2.创建空的数据包 3.接收数据
# 编写 UDP 通信程序
InetAddress 的使用:为了方便我们对 IP 地址的获取和操作,Java 提供了一个类 InetAddress 供我们使用 InetAddress:此类表示 Internet 协议(IP)地址
| 方法名 | 说明 |
|---|---|
| static InetAddress getLocalhost() | 获取本机的 IP 地址对象 |
| public static InetAddress getByName(String host) | 确定主机名称的 IP 地址。主机名称可以是机器名称,也可以是 IP 地址 |
| public String getHostName() | 获取此 IP 地址的主机名 |
| public String getHostAddress() | 返回文本显示中的 IP 地址字符串 |
DatagramSocket 的作用:表示 UDP 的发送端和接收端 send()发送数据,receive()接收数据
DatagramPacket 的作用表示数据包
发送端:
package com.itheima.demo02UDP_了解;
import java.io.IOException;
import java.net.*;
/*
目标:编写UDP的发送端
DatagramPacket(byte buf[], int offset, int length, InetAddress address, int port)
byte buf[]: 要发送的数据的字节数组
int offset: 从数组哪个位置开始发
int length: 发送多少数据
InetAddress address: 接收方的IP地址
int port: 接收方的端口
InetAddress.getLocalHost(): 获取本机的IP
InetAddress.getByName("192.168.75.96"): 别人的IP地址
注意:UDP协议不需要连接,没有接收端也不会报错,数据丢失啦
*/
public class UDPSender {
public static void main(String[] args) throws IOException {
System.out.println("发送端启动!");
// 1.创建发送端
DatagramSocket socket = new DatagramSocket();
// 2.创建数据包
byte[] bytes = "你好UDP".getBytes();
// DatagramPacket packet = new DatagramPacket(bytes, 0, bytes.length, InetAddress.getLocalHost(), 9527);
DatagramPacket packet = new DatagramPacket(bytes, 0, bytes.length, InetAddress.getByName("192.168.73.252"), 9527); // 接收方需要关闭防火墙
// 3.发送数据
socket.send(packet);
socket.close();
}
}
接收端:
package com.itheima.demo02UDP_了解;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;
/*
目标:编写UDP的接收端
DatagramPacket(byte buf[], int length)
创建空的数据包
byte buf[]: 用来保存数据的数组
int length: 数组一次可以接收多少数据
注意:要先运行接收端
*/
public class UDPReceiver {
public static void main(String[] args) throws IOException {
System.out.println("接收端启动!");
// 1.创建接收端, 会绑定本机的9527端口,别人通过9527端口就能找到这个接收端
DatagramSocket socket = new DatagramSocket(9527);
// 2.创建空的数据包
byte[] buf = new byte[1024];
DatagramPacket packet = new DatagramPacket(buf, buf.length);
// 3.接收数据, 接收到的数据放到包中
socket.receive(packet);
int length = packet.getLength(); // 获取接收数据的长度
System.out.println("接收端收到: " + new String(buf, 0, length));
socket.close();
}
}
# TCP 通信程序
# 介绍 TCP 通信流程
TCP 协议通信是需要连接的,建立连接后以流的形式传输,相当于打电话。
# 代码实现 TCP 客户端
实现 TCP 客户端步骤:
- 创建客户端
- 得到输出流写数据
- 得到输入流读取数据
- 关闭资源
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
/*
目标: 编写TCP客户端
Socket(String host, int port) 创建客户端, 会自动连接服务端
String host: 服务端的IP
int port: 服务端的端口
注意:
TCP协议先启动客户端,没有服务端,会出现连接异常
TCP程序一定要先运行服务端
*/
public class TCPClient {
public static void main(String[] args) throws IOException {
System.out.println("客户端启动啦!");
// 1.创建客户端, 创建好的客户端会自动连接 "127.0.0.1" 这台电脑的 10086端口
Socket socket = new Socket("127.0.0.1", 10086);
// 2.得到输出流写数据
OutputStream out = socket.getOutputStream();
out.write("你好约吗?".getBytes());
// 3.得到输入流读取数据
InputStream in = socket.getInputStream();
byte[] buf = new byte[1024];
int len = in.read(buf);
System.out.println("客户端收到: " + new String(buf, 0, len));
// 4.关闭资源
in.close();
out.close();
socket.close();
}
}
# 代码实现 TCP 服务端
实现 TCP 服务端步骤:
- 创建 TCP 服务端
- 同意客户端的请求
- 得到输入流读取数据
- 得到输出流写数据
- 关闭资源
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
/*
目标:编写TCP服务端
*/
public class TCPServer {
public static void main(String[] args) throws IOException {
System.out.println("服务端启动啦!");
// 1.创建TCP服务端, 创建的服务端会使用本机的10086端口,将来别的程序通过10086端口就能找到这个服务端
ServerSocket serverSocket = new ServerSocket(10086);
// 2.同意客户端的请求, 如果没有客户端连接就一直等
Socket socket = serverSocket.accept();
// 3.得到输入流读取数据
InputStream in = socket.getInputStream();
byte[] buf = new byte[1024];
int len = in.read(buf); // 没有数据会一直等
System.out.println("服务端收到: " + new String(buf, 0, len));
// 4.得到输出流写数据
OutputStream out = socket.getOutputStream();
out.write("老地方见!".getBytes());
// 5.关闭资源
out.close();
in.close();
socket.close();
serverSocket.close();
}
}
# 文件上传案例
# 理解 TCP 文件上传流程
客户端读取本地的文件,通过 Socket 流发送给服务端。服务端读取 Socket 流中的数据,写到文件中。
# 编写 TCP 文件上传客户端
- 创建客户端
- 创建文件输入流
- 得到 Socket 的输出流
- 循环读写数据
- 得到 Socket 输入流读取数据
- 关闭资源
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
/*
目标:编写文件上传的客户端
Socket(String host, int port) 创建客户端, 会自动连接服务端
String host: 服务端的IP
int port: 服务端的端口
*/
public class UploadClient {
public static void main(String[] args) throws IOException {
System.out.println("文件上传客户端启动啦!");
// 1.创建客户端, 客户端会连接127.0.0.1这个IP的电脑的9999端口
Socket socket = new Socket("127.0.0.1", 9999);
// 2.创建文件输入流
FileInputStream fis = new FileInputStream("D:\\MyFileTest\\xyz.png");
// 3.得到Socket的输出流
OutputStream out = socket.getOutputStream();
// 4.循环读写数据
byte[] buf = new byte[1024 * 8]; // 保存读取的数据
int len; // 保存读取的数量
while ((len = fis.read(buf)) != -1) {
out.write(buf, 0, len);
}
System.out.println("客户端发送文件完成!");
socket.shutdownOutput(); // 把客户端socket的输出流断掉,服务端的输入也就端掉啦.
// 5.得到Socket输入流读取数据
InputStream in = socket.getInputStream();
len = in.read(buf);
System.out.println("客户端收到: " + new String(buf, 0, len));
// 6.关闭资源
in.close();
out.close();
fis.close();
socket.close();
}
}
# 编写 TCP 文件上传服务端
- 创建服务端
- 同意客户端的连接
- 得到 Socket 输入流
- 创建文件输出流
- 循环读写数据
- 得到 Socket 的输出流写数据
- 关闭
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.UUID;
/*
目标:编写文件上传的服务端
我们现在学习的Socket和ServerSocket,没有数据会一直等待,不会结束,称为BIO(Blocking IO/阻塞式IO)
目标:解决上传文件重名问题
UUID生成一个随机的字符串
*/
public class UploadServer {
public static void main(String[] args) throws IOException {
System.out.println("文件上传服务端启动啦!");
// 1.创建服务端, 服务端会使用本机的9999端口, 将来客户端通过9999端口可以找到服务端
ServerSocket serverSocket = new ServerSocket(9999);
// 2.同意客户端的连接
Socket socket = serverSocket.accept();
// 3.得到Socket输入流
InputStream in = socket.getInputStream();
// 4.创建文件输出流
FileOutputStream fos = new FileOutputStream("study_day12\\upload\\1.png");
// 5.循环读写数据
byte[] buf = new byte[1024 * 8]; // 保存读取的数据
int len; // 保存读取的数量
while ((len = in.read(buf)) != -1) {
fos.write(buf, 0, len);
}
System.out.println("服务端接收完成!");
// 6.得到Socket的输出流写数据
OutputStream out = socket.getOutputStream();
out.write("上传完成!".getBytes());
// 7.关闭
out.close();
fos.close();
in.close();
socket.close();
serverSocket.close();
}
}
# 解决服务端无法停止问题
# 完成文件上传加强版
- 上传图片名称不同
1. 时间戳: long fileName = System.currentTimeMillis();
2. 随机名字: String fileName = UUID.randomUUID().toString();
- 支持多人上传
while(true) {
serverSocket.accept();
}
- 支持多人"同时"上传:线程池
// 创建线程池
ExecutorService pool = Executors.newFixedThreadPool(10);
while (true) {
// 2.同意客户端的连接
Socket socket = serverSocket.accept();
// 开始上传的代码写到新线程中
UploadRunnable up = new UploadRunnable(socket);
// 提交任务到线程池
pool.submit(up);
}
客户端代码:
package demo05文件上传多线程版本_练习;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
/*
目标:编写文件上传的客户端
Socket(String host, int port) 创建客户端, 会自动连接服务端
String host: 服务端的IP
int port: 服务端的端口
*/
public class UploadClient {
public static void main(String[] args) throws IOException {
System.out.println("文件上传客户端启动啦!");
// 1.创建客户端, 客户端会连接127.0.0.1这个IP的电脑的9999端口
Socket socket = new Socket("127.0.0.1", 9999);
// 2.创建文件输入流
FileInputStream fis = new FileInputStream("D:\\MyFileTest\\xyz.png");
// 3.得到Socket的输出流
OutputStream out = socket.getOutputStream();
// 4.循环读写数据
byte[] buf = new byte[1024 * 8]; // 保存读取的数据
int len; // 保存读取的数量
while ((len = fis.read(buf)) != -1) {
out.write(buf, 0, len);
}
System.out.println("客户端发送文件完成!");
socket.shutdownOutput(); // 把客户端socket的输出流断掉,服务端的输入也就端掉啦.
// 5.得到Socket输入流读取数据
InputStream in = socket.getInputStream();
len = in.read(buf);
System.out.println("客户端收到: " + new String(buf, 0, len));
// 6.关闭资源
in.close();
out.close();
fis.close();
socket.close();
}
}
服务端代码:
package demo05文件上传多线程版本_练习;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.UUID;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/*
目标:编写文件上传的服务端
我们现在学习的Socket和ServerSocket,没有数据会一直等待,不会结束,称为BIO(Blocking IO/阻塞式IO)
目标:解决上传文件重名问题
UUID生成一个随机的字符串
目标: 多人上传
循环同意accept,并传输数据
目标: 多人"同时"上传
使用多线程
*/
public class UploadServer {
public static void main(String[] args) throws IOException {
System.out.println("文件上传服务端启动啦!");
// 1.创建服务端, 服务端会使用本机的9999端口, 将来客户端通过9999端口可以找到服务端
ServerSocket serverSocket = new ServerSocket(9999);
// 创建线程池
ExecutorService pool = Executors.newFixedThreadPool(10);
while (true) {
// 2.同意客户端的连接
Socket socket = serverSocket.accept();
// 开始上传的代码写到新线程中
UploadRunnable up = new UploadRunnable(socket);
// 提交任务到线程池
pool.submit(up);
}
// 服务端不需要关闭
// serverSocket.close();
}
}
package demo05文件上传多线程版本_练习;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.util.UUID;
public class UploadRunnable implements Runnable {
// 成员变量
private Socket socket;
// 构造器给成员变量赋值
public UploadRunnable(Socket socket) {
this.socket = socket;
}
@Override
public void run() {
try {
System.out.println(socket.getRemoteSocketAddress() + "开始上传!");
// 3.得到Socket输入流
InputStream in = socket.getInputStream();
// 4.创建文件输出流
// 让文件名不同
// 1.时间戳: long fileName = System.currentTimeMillis();
// 2.随机名字
String fileName = UUID.randomUUID().toString();
FileOutputStream fos = new FileOutputStream("study_day12\\upload\\" + fileName + ".png");
// 5.循环读写数据
byte[] buf = new byte[1024 * 8]; // 保存读取的数据
int len; // 保存读取的数量
while ((len = in.read(buf)) != -1) {
fos.write(buf, 0, len);
}
System.out.println(socket.getRemoteSocketAddress() + "接收完成!");
// 6.得到Socket的输出流写数据
OutputStream out = socket.getOutputStream();
out.write("上传完成!".getBytes());
// 7.关闭
out.close();
fos.close();
in.close();
socket.close();
} catch (Exception e) {
System.out.println("文件上传失败: " + e.toString());
}
}
}
# 模拟 B\S 服务器
需求:模拟网站服务器,使用浏览器访问自己编写的服务端程序,浏览器得到服务器发送回的数据。
分析:
1. 准备页面数据,web文件夹。
2. 我们模拟服务器端,ServerSocket类监听端口,使用浏览器访问,查看网页效果
代码如下:
package demo07模拟网站服务器;
import java.io.IOException;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
public class WebServer {
public static void main(String[] args) throws IOException {
System.out.println("服务器启动成功!");
ServerSocket serverSocket = new ServerSocket(3006);
while (true) {
Socket socket = serverSocket.accept();
OutputStream outputStream = socket.getOutputStream();
outputStream.write("HTTP/1.1 200 OK\r\n".getBytes());
// 告诉浏览器返回一个 html ,编码是 utf-8
outputStream.write("Content-Type:text/html;charset=utf-8;\r\n".getBytes());
outputStream.write("\r\n".getBytes());
outputStream.write("<h1>你好 world</h1>".getBytes());
outputStream.close();
}
}
}
浏览器的底层是什么? TCP 客户端
服务器的底层是什么? TCP 服务端
# NIO
# NIO 概述介绍阻塞、非阻塞概念
NIO 概述:
- JDK1.4 以前: InputStream/OutputStream 称为 BIO(Blocking IO) 阻塞式 IO
- JDK1.4 推出了一套新的 IO 体系称为 NIO (New IO/ Not Blocking IO) 非阻塞式 IO
# 阻塞、非阻塞概念
阻塞和非阻塞都是处理 IO 数据的方式:
# 介绍 BIO 处理数据方式
# 介绍 NIO 处理数据方式
NIO 处理数据:
NIO 的优点:不需要一直等待,当有数据来才需要处理,没有数据可以做其他操作
# 介绍 NIO3 个角色
- Channel(通道)可以双向传输数据
- ByteBuffer 相当于之前 BIO 的 byte[],可以保存要发送和接收的数据, ByteBuffer 效率比 byte[] 要高,功能更强大
- Selector 选择器(相等于门卫大爷),可以管理多个连接

使用了多路复用,只需要一个线程就可以处理多个通道,降低内存占用率,减少 CPU 切换时间,在高并发、高频段业务环境下有非常重要的优势
# 演示 NIO 代码
package demo08_了解NIO;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
import java.util.Set;
public class Server {
public static void main(String[] args) throws IOException {
ServerSocketChannel serverSocketChannel1 = ServerSocketChannel.open();
serverSocketChannel1.bind(new InetSocketAddress(3006));
System.out.println("serverSocketChannel1 = " + serverSocketChannel1);
ServerSocketChannel serverSocketChannel2 = ServerSocketChannel.open();
serverSocketChannel2.bind(new InetSocketAddress(3007));
System.out.println("serverSocketChannel2 = " + serverSocketChannel2);
ServerSocketChannel serverSocketChannel3 = ServerSocketChannel.open();
serverSocketChannel3.bind(new InetSocketAddress(3008));
System.out.println("serverSocketChannel3 = " + serverSocketChannel3);
// 设置为非阻塞式
serverSocketChannel1.configureBlocking(false);
serverSocketChannel2.configureBlocking(false);
serverSocketChannel3.configureBlocking(false);
// 得到选择器
Selector selector = Selector.open();
// 将通道注册到选择器上
serverSocketChannel1.register(selector, SelectionKey.OP_ACCEPT);
serverSocketChannel2.register(selector, SelectionKey.OP_ACCEPT);
serverSocketChannel3.register(selector, SelectionKey.OP_ACCEPT);
while (true) {
// Selector的select()方法 作用:查看是否有客户端连接
int count = selector.select();
// Selector的selectedKeys()方法
// 此方法返回一个Set<SelectionKey>集合,表示:当前已连接的通道的集合。每个已连接通道同一封装为一个SelectionKey对象。
// 取出已经连接的服务端Channel
Set<SelectionKey> selectionKeys = selector.selectedKeys();
Iterator<SelectionKey> iterator = selectionKeys.iterator();
while (iterator.hasNext()) {
SelectionKey selectionKey = iterator.next();
ServerSocketChannel ssChannel = (ServerSocketChannel) selectionKey.channel();
SocketChannel socketChannel = ssChannel.accept();// 同意客户端的请求
System.out.println("我处理了ServerSocketChanner的连接: " + ssChannel);
// 接收客户端发过来的数据
ByteBuffer buffer = ByteBuffer.allocate(1024);
int len = socketChannel.read(buffer); // 接收的数据保存buffer中,返回接收的个数
System.out.println(ssChannel + ", 服务端收到: " + new String(buffer.array(), 0, len));
// 已经连接的通道使用完毕必须删除,不然再次调用selectkeys的时候还是会迭代出来。
iterator.remove();
}
}
}
}
package demo08_了解NIO;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SocketChannel;
/*
1.创建客户端,连接服务器
2.通过通道发数据
3.关闭资源
*/
public class CLient3006 {
public static void main(String[] args) throws IOException {
// 1.创建客户端,连接服务器
SocketChannel socketChannel = SocketChannel.open();
socketChannel.connect(new InetSocketAddress("127.0.0.1", 3006));
// 2.通过通道发数据
ByteBuffer buffer = ByteBuffer.allocate(1024);
buffer.put("hello, 3006".getBytes());
buffer.flip(); // 方便下次获取Buffer中的数据
socketChannel.write(buffer);
// 3.关闭资源
socketChannel.close();
}
}
package demo08_了解NIO;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SocketChannel;
public class Client3007 {
public static void main(String[] args) throws IOException {
// 1.创建客户端,连接服务器
SocketChannel socketChannel = SocketChannel.open();
socketChannel.connect(new InetSocketAddress("127.0.0.1", 3007));
// 2.通过通道发数据
ByteBuffer buffer = ByteBuffer.allocate(1024);
buffer.put("hello, ".getBytes());
buffer.flip(); // 方便下次获取Buffer中的数据
socketChannel.write(buffer);
// 3.关闭资源
socketChannel.close();
}
}
# commons-io 工具包
commons-io 概述:
- commons-io 是 apache 开源基金组织提供的一组有关 IO 操作的类库,可以挺提高 IO 功能开发的效率。
- commons-io 工具包提供了很多有关 io 操作的类。有两个主要的类 FileUtils, IOUtils
FileUtils 主要有如下方法:
| 方法名 | 说明 |
|---|---|
| String readFileToString(File file, String encoding) | 读取文件中的数据, 返回字符串 |
| void copyFile(File srcFile, File destFile) | 复制文件。 |
| void copyDirectoryToDirectory(File srcDir, File destDir) | 复制文件夹。 |
commons-io 使用步骤:
- 导入 commons-io-2.6.jar
- 在项目中创建一个文件夹:lib
- 将 commons-io-2.6.jar 文件复制到 lib 文件夹
- 在 jar 文件上点右键,选择 Add as Library -> 点击 OK
- 在类中导包使用

使用 commons-io 实现读文件、复制文件、复制文件夹的功能:
package demo09_commons_io使用;
import org.apache.commons.io.FileUtils;
import java.io.File;
import java.io.IOException;
public class Demo {
public static void main(String[] args) throws IOException {
// 读文件
String s = FileUtils.readFileToString(new File("D:\\learn\\java\\code\\javaUp\\day12\\doc\\1.txt"), "utf-8");
System.out.println(s);
// 复制文件
FileUtils.copyFile(new File("D:\\learn\\java\\code\\javaUp\\day12\\doc\\1.txt"), new File("D:\\learn\\java\\code\\javaUp\\day12\\doc\\2.txt"));
// 复制文件夹
FileUtils.copyDirectoryToDirectory(new File("D:\\learn\\java\\code\\javaUp\\day12\\doc"), new File("D:\\learn\\java\\code\\javaUp\\day12\\doc2"));
}
}
