Apache Commons 工具类使用教程文档
本文档面向 Java 开发工程师,整理了 Apache Commons 系列工具库中最常用、最实用的方法和说明。 涵盖 Commons Lang3、Commons IO、Commons Collections4 三大核心组件。
目录
- 依赖引入
- Commons Lang3 - 核心语言增强
- 2.1 StringUtils(字符串工具)
- 2.2 ArrayUtils(数组工具)
- 2.3 ObjectUtils(对象工具)
- 2.4 NumberUtils(数字工具)
- 2.5 DateUtils / DateFormatUtils(日期工具)
- 2.6 RandomStringUtils(随机字符串)
- Commons IO - IO 操作工具
- 3.1 FileUtils(文件操作)
- 3.2 IOUtils(流操作)
- 3.3 FilenameUtils(文件名操作)
- Commons Collections4 - 集合框架扩展
- 4.1 CollectionUtils(集合工具)
- 4.2 MapUtils(Map 工具)
- 最佳实践总结
1. 依赖引入
在 pom.xml 中添加以下依赖:
xml
<!-- Apache Commons Lang3 -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.12.0</version>
</dependency>
<!-- Apache Commons IO -->
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.11.0</version>
</dependency>
<!-- Apache Commons Collections4 -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-collections4</artifactId>
<version>4.4</version>
</dependency>2. Commons Lang3
2.1 StringUtils — 字符串工具类
StringUtils 是 Apache Commons 中使用频率最高的工具类,提供了大量字符串操作方法,null-safe(安全处理 null) 是其最大特点。
2.1.1 空值判断
| 方法 | 说明 | 示例 |
|---|---|---|
isEmpty(CharSequence) | 判断是否为 null 或长度为 0 | "" → true, " " → false, null → true |
isBlank(CharSequence) | 判断是否为 null、长度为 0 或仅含空白字符 | "" → true, " " → true, null → true |
isNotEmpty(CharSequence) | isEmpty 的反向判断 | |
isNotBlank(CharSequence) | isBlank 的反向判断 | |
defaultString(String, String) | 为 null 提供默认值 | defaultString(null, "default") → "default" |
defaultIfBlank(T, T) | 为 blank 提供默认值 | defaultIfBlank(" ", "default") → "default" |
java
import org.apache.commons.lang3.StringUtils;
public class StringUtilsDemo {
public static void main(String[] args) {
String str1 = null;
String str2 = "";
String str3 = " ";
String str4 = "Hello";
System.out.println(StringUtils.isEmpty(str1)); // true
System.out.println(StringUtils.isEmpty(str2)); // true
System.out.println(StringUtils.isEmpty(str3)); // false (空格不是empty)
System.out.println(StringUtils.isBlank(str3)); // true (空格是blank)
System.out.println(StringUtils.isBlank(str4)); // false
// 安全获取默认值
String result = StringUtils.defaultString(str1, "default");
System.out.println(result); // "default"
String result2 = StringUtils.defaultIfBlank(str3, "default");
System.out.println(result2); // "default"
}
}2.1.2 字符串截取
| 方法 | 说明 | 示例 |
|---|---|---|
substring(String, int) | 从指定位置截取 | substring("Hello", 2) → "llo" |
substringBefore(String, String) | 截取分隔符前的内容 | substringBefore("a@b.com", "@") → "a" |
substringAfter(String, String) | 截取分隔符后的内容 | substringAfter("a@b.com", "@") → "b.com" |
substringBetween(String, String) | 截取两个标记之间的内容 | substringBetween("[abc]", "[", "]") → "abc" |
left(String, int) | 从左侧截取 n 个字符 | left("Hello", 2) → "He" |
right(String, int) | 从右侧截取 n 个字符 | right("Hello", 2) → "lo" |
mid(String, int, int) | 从中间指定位置截取 | mid("Hello", 1, 3) → "ell" |
java
String str = "user@example.com";
String user = StringUtils.substringBefore(str, "@"); // "user"
String domain = StringUtils.substringAfter(str, "@"); // "example.com"
String middle = StringUtils.substringBetween("[data]", "[", "]"); // "data"2.1.3 字符串填充与对齐
| 方法 | 说明 | 示例 |
|---|---|---|
leftPad(String, int, char) | 左侧填充至指定长度 | leftPad("5", 3, '0') → "005" |
rightPad(String, int, char) | 右侧填充至指定长度 | rightPad("5", 3, '0') → "500" |
center(String, int, char) | 两侧居中填充 | center("a", 5, '*') → "**a**" |
repeat(String, int) | 重复字符串 | repeat("ab", 3) → "ababab" |
abbreviate(String, int) | 缩略字符串,超出显示省略号 | abbreviate("Hello World", 8) → "Hello..." |
java
// 时间格式化补零
String time = StringUtils.leftPad(String.valueOf(5), 2, '0'); // "05"
// 订单号补零
String orderNo = StringUtils.leftPad("123", 8, '0'); // "00000123"
// 居中显示
String title = StringUtils.center("Title", 20, '='); // "=======Title========"2.1.4 字符串替换与删除
| 方法 | 说明 | 示例 |
|---|---|---|
replace(String, String, String) | 替换所有匹配 | replace("abcabc", "a", "x") → "xbcxbc" |
replaceOnce(String, String, String) | 仅替换第一次匹配 | |
replaceIgnoreCase(String, String, String) | 忽略大小写替换 | |
deleteWhitespace(String) | 删除所有空白字符 | deleteWhitespace("a b\nc") → "abc" |
remove(String, String) | 删除所有指定子串 | remove("abcabc", "a") → "bcbc" |
removeStart(String, String) | 删除开头匹配 | removeStart("www.example.com", "www.") → "example.com" |
removeEnd(String, String) | 删除结尾匹配 | removeEnd("file.txt", ".txt") → "file" |
strip(String, String) | 删除两端指定字符 | strip("xxHelloxx", "x") → "Hello" |
trimToNull(String) | 去除两端空白,空白则返回 null | trimToNull(" ") → null |
trimToEmpty(String) | 去除两端空白,空白则返回空串 | trimToEmpty(" ") → "" |
java
// 去除所有空白(包括换行、制表符)
String clean = StringUtils.deleteWhitespace("Hello\nWorld\t!"); // "HelloWorld!"
// 批量替换敏感词
String content = StringUtils.replace("bad word here", "bad", "***");
// 去除 URL 前缀
String url = StringUtils.removeStart("https://example.com", "https://"); // "example.com"2.1.5 字符串比较与包含
| 方法 | 说明 | 示例 |
|---|---|---|
equals(CharSequence, CharSequence) | null-safe 比较 | equals(null, null) → true |
equalsIgnoreCase(CharSequence, CharSequence) | 忽略大小写比较 | |
contains(CharSequence, CharSequence) | null-safe 包含判断 | contains(null, "a") → false |
containsIgnoreCase(CharSequence, CharSequence) | 忽略大小写包含 | |
containsAny(CharSequence, CharSequence...) | 包含任意一个字符 | containsAny("abc", "x", "b") → true |
containsOnly(CharSequence, CharSequence) | 是否只包含指定字符 | containsOnly("abab", "ab") → true |
startsWith(CharSequence, CharSequence) | null-safe 前缀判断 | |
endsWith(CharSequence, CharSequence) | null-safe 后缀判断 | |
startsWithIgnoreCase(CharSequence, CharSequence) | 忽略大小写前缀判断 | |
indexOfAny(String, String...) | 查找任意子串首次出现位置 | indexOfAny("abc", "x", "b") → 1 |
countMatches(CharSequence, CharSequence) | 统计子串出现次数 | countMatches("abab", "a") → 2 |
java
// 安全比较,避免 NPE
if (StringUtils.equals(input, "expected")) { ... }
// 检查是否包含任意关键词
boolean hasKeyword = StringUtils.containsAny(title, "error", "fail", "exception");
// 统计字符出现次数
int count = StringUtils.countMatches("hello world", "l"); // 32.1.6 字符串分割与合并
| 方法 | 说明 | 示例 |
|---|---|---|
split(String, String) | 按分隔符分割为数组 | split("a,b,c", ",") → ["a","b","c"] |
splitByWholeSeparator(String, String) | 按完整分隔符分割 | splitByWholeSeparator("a::b::c", "::") |
splitPreserveAllTokens(String, String) | 保留空 token | splitPreserveAllTokens("a,,c", ",") → ["a","","c"] |
join(Object[], String) | 用分隔符合并数组 | join(["a","b","c"], "-") → "a-b-c" |
join(Iterable, String) | 用分隔符合并集合 | |
joinWith(String, Object...) | 用指定分隔符合并 | joinWith("-", "a", "b", "c") → "a-b-c" |
join(Object[], String, int, int) | 合并指定范围 |
java
// 分割 CSV
String[] parts = StringUtils.split("apple,banana,orange", ",");
// 保留空值的分割
String[] parts2 = StringUtils.splitPreserveAllTokens("a,,c", ","); // ["a", "", "c"]
// 合并列表
List<String> list = Arrays.asList("a", "b", "c");
String result = StringUtils.join(list, " | "); // "a | b | c"
// 合并多个参数
String path = StringUtils.joinWith("/", "api", "v1", "users"); // "api/v1/users"2.1.7 其他实用方法
| 方法 | 说明 | 示例 |
|---|---|---|
reverse(String) | 反转字符串 | reverse("abc") → "cba" |
swapCase(String) | 大小写互换 | swapCase("Hello") → "hELLO" |
capitalize(String) | 首字母大写 | capitalize("hello") → "Hello" |
uncapitalize(String) | 首字母小写 | uncapitalize("Hello") → "hello" |
upperCase(String) / lowerCase(String) | 大小写转换 | |
isNumeric(String) | 是否纯数字 | isNumeric("123") → true |
isAlpha(String) | 是否纯字母 | isAlpha("abc") → true |
isAlphanumeric(String) | 是否字母或数字 | |
isWhitespace(String) | 是否纯空白 | |
difference(String, String) | 获取两字符串差异部分 | difference("ab", "abc") → "c" |
getCommonPrefix(String...) | 获取公共前缀 | getCommonPrefix("abc", "abd") → "ab" |
normalizeSpace(String) | 规范化空格(多个空格合并为一个) |
java
// 首字母大写
String name = StringUtils.capitalize("tom"); // "Tom"
// 验证输入
boolean isNumber = StringUtils.isNumeric(userInput);
// 获取差异
String diff = StringUtils.difference("version-1.0", "version-1.1"); // "1.1"
// 规范化空格
String normalized = StringUtils.normalizeSpace("Hello World"); // "Hello World"2.2 ArrayUtils — 数组工具类
ArrayUtils 提供了数组的创建、操作、搜索等 null-safe 方法。
| 方法 | 说明 | 示例 |
|---|---|---|
isEmpty(Object[]) | 判断数组是否为空或 null | |
isNotEmpty(Object[]) | 判断数组非空 | |
contains(Object[], Object) | 判断是否包含元素 | |
indexOf(Object[], Object) | 查找元素索引 | |
lastIndexOf(Object[], Object) | 反向查找元素索引 | |
add(Object[], Object) | 添加元素 | add(["a"], "b") → ["a","b"] |
addAll(Object[], Object...) | 合并数组 | |
remove(Object[], int) | 按索引删除 | |
removeElement(Object[], Object) | 按值删除 | |
removeAll(Object[], int...) | 按多个索引删除 | |
subarray(Object[], int, int) | 截取子数组 | |
toObject(primitive[]) | 基本类型转包装类型 | toObject(new int[]{1,2}) → [Integer] |
toPrimitive(Object[]) | 包装类型转基本类型 | |
clone(Object[]) | 克隆数组 | |
reverse(Object[]) | 反转数组 | |
swap(Object[], int, int) | 交换元素 | |
shuffle(Object[]) | 随机打乱 | |
nullToEmpty(Object[]) | null 转空数组 | |
getLength(Object) | 安全获取长度 | getLength(null) → 0 |
isSameLength(Object[], Object[]) | 比较长度 | |
toMap(Object[]) | 数组转 Map | toMap(new String[][]k) |
java
import org.apache.commons.lang3.ArrayUtils;
public class ArrayUtilsDemo {
public static void main(String[] args) {
String[] arr = {"a", "b", "c"};
// 安全判断
System.out.println(ArrayUtils.isEmpty(arr)); // false
System.out.println(ArrayUtils.isEmpty(null)); // true
// 查找
System.out.println(ArrayUtils.contains(arr, "b")); // true
System.out.println(ArrayUtils.indexOf(arr, "b")); // 1
// 添加元素
String[] newArr = ArrayUtils.add(arr, "d"); // ["a","b","c","d"]
String[] merged = ArrayUtils.addAll(arr, new String[]{"e", "f"});
// 删除
String[] removed = ArrayUtils.removeElement(arr, "b"); // ["a","c"]
// 截取
String[] sub = ArrayUtils.subarray(arr, 0, 2); // ["a","b"]
// 反转
ArrayUtils.reverse(arr); // ["c","b","a"]
// 基本类型转换
Integer[] boxed = ArrayUtils.toObject(new int[]{1, 2, 3});
int[] primitive = ArrayUtils.toPrimitive(new Integer[]{1, 2, 3});
// 数组转 Map(二维数组,每个元素是 key-value 对)
Map<String, String> map = ArrayUtils.toMap(new String[][]{
{"name", "Tom"},
{"age", "20"}
});
}
}2.3 ObjectUtils — 对象工具类
| 方法 | 说明 | 示例 |
|---|---|---|
isEmpty(Object) | 判断对象是否为空 | 支持 String、Collection、Map、Array |
isNotEmpty(Object) | 判断对象非空 | |
defaultIfNull(T, T) | null 时返回默认值 | defaultIfNull(null, "default") → "default" |
firstNonNull(T...) | 返回第一个非 null 值 | firstNonNull(null, null, "a") → "a" |
allNotNull(Object...) | 判断是否全部非 null | |
anyNotNull(Object...) | 判断是否至少一个非 null | |
max(Comparable...) / min(Comparable...) | 比较获取最大/最小值 | |
compare(T, T) | null-safe 比较 | |
notEqual(Object, Object) | null-safe 不等判断 | |
identityToString(Object) | 获取对象 identity 字符串 | |
toString(Object, String) | null-safe toString | toString(null, "null") → "null" |
clone(Object) | 克隆对象(如果支持) |
java
import org.apache.commons.lang3.ObjectUtils;
public class ObjectUtilsDemo {
public static void main(String[] args) {
String str = null;
List<String> list = new ArrayList<>();
Map<String, String> map = null;
// 统一判断空值
System.out.println(ObjectUtils.isEmpty(str)); // true
System.out.println(ObjectUtils.isEmpty(list)); // true (集合为空)
System.out.println(ObjectUtils.isEmpty(map)); // true (null)
// 获取默认值
String result = ObjectUtils.defaultIfNull(str, "default"); // "default"
// 获取第一个非 null 值
String first = ObjectUtils.firstNonNull(null, null, "first", "second"); // "first"
// 比较
Integer max = ObjectUtils.max(1, 5, 3, 2); // 5
Integer min = ObjectUtils.min(1, 5, 3, 2); // 1
// null-safe 比较
int cmp = ObjectUtils.compare(null, "a"); // -1 (null 视为更小)
}
}2.4 NumberUtils — 数字工具类
| 方法 | 说明 | 示例 |
|---|---|---|
toInt(String) / toInt(String, int) | 字符串转 int,失败返回默认值 | toInt("abc", 0) → 0 |
toLong(String) / toLong(String, long) | 字符串转 long | |
toDouble(String) / toDouble(String, double) | 字符串转 double | |
toFloat(String) / toFloat(String, float) | 字符串转 float | |
toShort(String) / toShort(String, short) | 字符串转 short | |
toByte(String) / toByte(String, byte) | 字符串转 byte | |
createNumber(String) | 智能创建 Number 对象 | createNumber("123") → Integer |
isDigits(String) | 是否纯数字(无符号) | isDigits("123") → true |
isParsable(String) | 是否可解析为数字 | isParsable("-123.45") → true |
isNumber(String) | 是否有效数字(更严格) | |
min(int...) / max(int...) | 获取最小/最大值 | min(1, 5, 3) → 1 |
compare(int, int) | 比较两个 int |
java
import org.apache.commons.lang3.math.NumberUtils;
public class NumberUtilsDemo {
public static void main(String[] args) {
// 安全转换,避免 NumberFormatException
int num = NumberUtils.toInt("abc", 0); // 0
int num2 = NumberUtils.toInt("123", 0); // 123
long l = NumberUtils.toLong("9999999999"); // 9999999999L
double d = NumberUtils.toDouble("3.14"); // 3.14
// 判断是否为数字
System.out.println(NumberUtils.isDigits("123")); // true
System.out.println(NumberUtils.isDigits("-123")); // false (有负号)
System.out.println(NumberUtils.isParsable("-123.45")); // true
// 获取最值
int min = NumberUtils.min(5, 2, 8, 1); // 1
int max = NumberUtils.max(5, 2, 8, 1); // 8
// 比较
int cmp = NumberUtils.compare(5, 3); // 1
}
}2.5 DateUtils / DateFormatUtils — 日期工具类
DateUtils — 日期计算与操作
| 方法 | 说明 | 示例 |
|---|---|---|
addYears(Date, int) | 加减年份 | addYears(now, 1) |
addMonths(Date, int) | 加减月份 | |
addWeeks(Date, int) | 加减周 | |
addDays(Date, int) | 加减天数 | |
addHours(Date, int) | 加减小时 | |
addMinutes(Date, int) | 加减分钟 | |
addSeconds(Date, int) | 加减秒 | |
addMilliseconds(Date, int) | 加减毫秒 | |
setYears(Date, int) | 设置年份 | |
setMonths(Date, int) | 设置月份 | |
setDays(Date, int) | 设置日期 | |
truncate(Date, int) | 截断到指定精度 | truncate(date, Calendar.MONTH) |
round(Date, int) | 四舍五入到指定精度 | |
ceiling(Date, int) | 向上取整到指定精度 | |
isSameDay(Date, Date) | 是否同一天 | |
isSameInstant(Date, Date) | 是否同一时刻 |
java
import org.apache.commons.lang3.time.DateUtils;
import java.util.Date;
import java.util.Calendar;
public class DateUtilsDemo {
public static void main(String[] args) {
Date now = new Date();
// 日期计算
Date tomorrow = DateUtils.addDays(now, 1);
Date lastMonth = DateUtils.addMonths(now, -1);
Date nextYear = DateUtils.addYears(now, 1);
// 截断到月初
Date firstDayOfMonth = DateUtils.truncate(now, Calendar.MONTH);
// 截断到当天开始
Date startOfDay = DateUtils.truncate(now, Calendar.DATE);
// 判断是否同一天
boolean sameDay = DateUtils.isSameDay(now, tomorrow); // false
// 设置具体日期
Date setDay = DateUtils.setDays(now, 15); // 设置为当月15号
}
}DateFormatUtils — 日期格式化
| 方法 | 说明 | 示例 |
|---|---|---|
format(Date, String) | 按指定格式格式化 | format(date, "yyyy-MM-dd") |
format(Date, String, TimeZone) | 带时区格式化 | |
formatUTC(Date, String) | UTC 时间格式化 | |
ISO_8601_EXTENDED_DATETIME_FORMAT | ISO 8601 格式常量 | |
ISO_DATETIME_FORMAT | ISO 日期时间格式 |
java
import org.apache.commons.lang3.time.DateFormatUtils;
import java.util.Date;
public class DateFormatUtilsDemo {
public static void main(String[] args) {
Date now = new Date();
// 常用格式化
String dateStr = DateFormatUtils.format(now, "yyyy-MM-dd HH:mm:ss");
String dateOnly = DateFormatUtils.format(now, "yyyy-MM-dd");
String timeOnly = DateFormatUtils.format(now, "HH:mm:ss");
// 使用预定义格式
String isoDate = DateFormatUtils.ISO_8601_EXTENDED_DATETIME_FORMAT.format(now);
// UTC 格式化
String utc = DateFormatUtils.formatUTC(now, "yyyy-MM-dd'T'HH:mm:ss'Z'");
System.out.println(dateStr); // 2024-01-15 14:30:00
System.out.println(isoDate); // 2024-01-15T14:30:00
}
}2.6 RandomStringUtils — 随机字符串生成
| 方法 | 说明 | 示例 |
|---|---|---|
random(int) | 生成指定长度随机字符串 | random(10) |
randomAlphabetic(int) | 纯字母随机字符串 | randomAlphabetic(8) → "kDjMnpQw" |
randomAlphanumeric(int) | 字母+数字随机字符串 | randomAlphanumeric(10) |
randomNumeric(int) | 纯数字随机字符串 | randomNumeric(6) → "837291" |
randomAscii(int) | ASCII 字符随机字符串 | |
random(int, boolean, boolean) | 自定义是否包含字母/数字 | |
random(int, int, int, boolean, boolean, char[]) | 完全自定义 |
java
import org.apache.commons.lang3.RandomStringUtils;
public class RandomStringUtilsDemo {
public static void main(String[] args) {
// 生成验证码
String verifyCode = RandomStringUtils.randomNumeric(6); // "837291"
// 生成随机密码
String password = RandomStringUtils.randomAlphanumeric(12); // "aB3dE7fG9hJ2"
// 生成纯字母随机串
String token = RandomStringUtils.randomAlphabetic(32); // 用于 token
// 生成指定范围的随机串
String custom = RandomStringUtils.random(8, 33, 126, false, false, null);
// 从 ASCII 33-126 中随机选取
}
}3. Commons IO
3.1 FileUtils — 文件操作工具类
FileUtils 提供了文件的读写、复制、移动、删除等一站式操作,全部 null-safe 且自动处理异常。
3.1.1 文件读写
| 方法 | 说明 | 示例 |
|---|---|---|
readFileToString(File, String) | 读取文件为字符串 | readFileToString(file, "UTF-8") |
readFileToByteArray(File) | 读取文件为字节数组 | |
readLines(File, String) | 读取文件为字符串列表 | |
lineIterator(File, String) | 逐行读取(大文件友好) | |
writeStringToFile(File, String, String) | 字符串写入文件 | |
writeStringToFile(File, String, String, boolean) | 追加写入 | 第四个参数 true=追加 |
write(File, CharSequence, String) | 写入字符序列 | |
writeByteArrayToFile(File, byte[]) | 字节数组写入文件 | |
writeLines(File, String, Collection) | 按行写入集合 |
java
import org.apache.commons.io.FileUtils;
import java.io.File;
import java.io.IOException;
import java.util.List;
public class FileUtilsReadWriteDemo {
public static void main(String[] args) throws IOException {
File file = new File("test.txt");
// 读取整个文件为字符串
String content = FileUtils.readFileToString(file, "UTF-8");
// 读取为字节数组
byte[] bytes = FileUtils.readFileToByteArray(file);
// 按行读取
List<String> lines = FileUtils.readLines(file, "UTF-8");
for (String line : lines) {
System.out.println(line);
}
// 逐行读取(适合大文件)
LineIterator it = FileUtils.lineIterator(file, "UTF-8");
try {
while (it.hasNext()) {
System.out.println(it.nextLine());
}
} finally {
LineIterator.closeQuietly(it);
}
// 写入字符串
FileUtils.writeStringToFile(file, "Hello World", "UTF-8");
// 追加写入
FileUtils.writeStringToFile(file, "\nAppend line", "UTF-8", true);
// 写入多行
List<String> data = Arrays.asList("line1", "line2", "line3");
FileUtils.writeLines(file, "UTF-8", data);
}
}3.1.2 文件复制
| 方法 | 说明 | 示例 |
|---|---|---|
copyFile(File, File) | 复制文件 | |
copyFile(File, File, boolean) | 复制文件(保留文件属性) | 第三个参数 true=保留 |
copyFileToDirectory(File, File) | 复制文件到目录 | |
copyDirectory(File, File) | 复制整个目录 | |
copyDirectoryToDirectory(File, File) | 复制目录到目录 | |
copyDirectory(File, File, FileFilter) | 带过滤器的目录复制 | |
copyInputStreamToFile(InputStream, File) | 输入流复制到文件 | |
copyURLToFile(URL, File) | URL 内容复制到文件 | |
copyFile(File, OutputStream) | 文件复制到输出流 |
java
import org.apache.commons.io.FileUtils;
import java.io.File;
import java.io.IOException;
import java.net.URL;
public class FileUtilsCopyDemo {
public static void main(String[] args) throws IOException {
File srcFile = new File("source.txt");
File destFile = new File("dest.txt");
File srcDir = new File("sourceDir");
File destDir = new File("destDir");
// 复制文件
FileUtils.copyFile(srcFile, destFile);
// 复制文件并保留属性(修改时间等)
FileUtils.copyFile(srcFile, destFile, true);
// 复制文件到指定目录
FileUtils.copyFileToDirectory(srcFile, destDir);
// 复制整个目录
FileUtils.copyDirectory(srcDir, destDir);
// 复制目录到目录下(destDir/sourceDir/...)
FileUtils.copyDirectoryToDirectory(srcDir, destDir);
// 从输入流复制到文件
InputStream is = new FileInputStream(srcFile);
FileUtils.copyInputStreamToFile(is, new File("output.txt"));
// 从 URL 下载文件
FileUtils.copyURLToFile(
new URL("https://example.com/file.txt"),
new File("downloaded.txt")
);
}
}3.1.3 文件移动与重命名
| 方法 | 说明 | 示例 |
|---|---|---|
moveFile(File, File) | 移动/重命名文件 | |
moveFileToDirectory(File, File, boolean) | 移动文件到目录 | 第三个参数 true=创建目录 |
moveDirectory(File, File) | 移动目录 | |
moveDirectoryToDirectory(File, File, boolean) | 移动目录到目录 | |
moveToDirectory(File, File, boolean) | 智能移动到目录 |
java
// 重命名文件
FileUtils.moveFile(new File("old.txt"), new File("new.txt"));
// 移动文件到目录
FileUtils.moveFileToDirectory(new File("file.txt"), new File("backup/"), true);
// 移动目录
FileUtils.moveDirectory(new File("oldDir"), new File("newDir"));3.1.4 文件删除
| 方法 | 说明 | 示例 |
|---|---|---|
delete(File) | 删除文件或目录 | 失败抛异常 |
deleteDirectory(File) | 递归删除目录 | |
deleteQuietly(File) | 安静删除(不抛异常) | |
forceDelete(File) | 强制删除(包括只读文件) | |
forceDeleteOnExit(File) | JVM 退出时删除 | 适合临时文件 |
cleanDirectory(File) | 清空目录内容(保留目录) |
java
// 删除文件
FileUtils.delete(new File("file.txt"));
// 递归删除目录
FileUtils.deleteDirectory(new File("tempDir"));
// 安全删除(不抛异常)
FileUtils.deleteQuietly(new File("maybeNotExist.txt"));
// 强制删除只读文件
FileUtils.forceDelete(new File("readonly.txt"));
// JVM 退出时删除(临时文件)
FileUtils.forceDeleteOnExit(new File("temp.tmp"));
// 清空目录但保留目录本身
FileUtils.cleanDirectory(new File("logs/"));3.1.5 目录操作
| 方法 | 说明 | 示例 |
|---|---|---|
forceMkdir(File) | 强制创建目录(含父目录) | |
forceMkdirParent(File) | 强制创建父目录 | |
getTempDirectory() | 获取系统临时目录 | |
getTempDirectoryPath() | 获取临时目录路径 | |
getUserDirectory() | 获取用户主目录 | |
getUserDirectoryPath() | 获取用户主目录路径 | |
directoryContains(File, File) | 判断目录是否包含文件 | |
listFiles(File, String[], boolean) | 按扩展名列文件 | |
listFiles(File, IOFileFilter, IOFileFilter) | 按过滤器列文件 | |
iterateFiles(File, IOFileFilter, IOFileFilter) | 迭代器方式列文件 | |
convertFileCollectionToFileArray(Collection) | 集合转数组 |
java
// 创建多级目录
FileUtils.forceMkdir(new File("a/b/c/d"));
// 创建文件的父目录
FileUtils.forceMkdirParent(new File("a/b/c/file.txt"));
// 获取系统目录
File tempDir = FileUtils.getTempDirectory(); // C:\Users\xxx\AppData\Local\Temp
File userDir = FileUtils.getUserDirectory(); // C:\Users\xxx
// 列出所有 .txt 和 .java 文件
List<File> txtFiles = (List<File>) FileUtils.listFiles(
new File("src/"),
new String[]{"txt", "java"},
true // 递归子目录
);
// 使用过滤器
IOFileFilter filter = new SuffixFileFilter(".txt");
Collection<File> files = FileUtils.listFiles(new File("dir"), filter, null);3.1.6 文件信息查询
| 方法 | 说明 | 示例 |
|---|---|---|
sizeOf(File) | 获取文件/目录大小 | 返回 long |
sizeOfAsBigInteger(File) | 获取大小(BigInteger) | |
sizeOfDirectory(File) | 获取目录大小 | |
byteCountToDisplaySize(long) | 字节转可读大小 | byteCountToDisplaySize(1024) → "1 KB" |
isFileNewer(File, File) | 比较文件新旧 | |
isFileNewer(File, Date) | 与日期比较 | |
isFileOlder(File, File) | 比较文件新旧 | |
checkSum(File, Checksum) | 计算校验和 | |
checkSumCRC32(File) | 计算 CRC32 | |
contentEquals(File, File) | 比较文件内容 | |
contentEqualsIgnoreEOL(File, File, String) | 忽略换行符比较 | |
waitFor(File, int) | 等待文件创建 | 超时秒数 |
touch(File) | 创建文件或更新修改时间 | |
openInputStream(File) | 安全打开输入流 | |
openOutputStream(File) | 安全打开输出流 | |
openOutputStream(File, boolean) | 追加模式打开输出流 |
java
// 获取可读的文件大小
long size = FileUtils.sizeOf(new File("video.mp4"));
String readable = FileUtils.byteCountToDisplaySize(size); // "156 MB"
// 比较文件新旧
boolean isNewer = FileUtils.isFileNewer(new File("a.txt"), new File("b.txt"));
// 计算 CRC32
long crc32 = FileUtils.checksumCRC32(new File("file.zip"));
// 比较文件内容
boolean same = FileUtils.contentEquals(new File("a.txt"), new File("b.txt"));
// 创建空文件或更新修改时间
FileUtils.touch(new File("marker.txt"));3.2 IOUtils — 流操作工具类
IOUtils 提供了输入输出流的通用操作方法,简化流的读写和关闭。
| 方法 | 说明 | 示例 |
|---|---|---|
toString(InputStream, String) | 输入流转字符串 | toString(is, "UTF-8") |
toString(Reader) | 读取 Reader 内容 | |
toByteArray(InputStream) | 输入流转字节数组 | |
toByteArray(Reader) | Reader 转字节数组 | |
toInputStream(String, String) | 字符串转输入流 | |
readLines(InputStream, String) | 按行读取到列表 | |
write(String, OutputStream, String) | 字符串写入输出流 | |
write(byte[], OutputStream) | 字节数组写入输出流 | |
copy(InputStream, OutputStream) | 拷贝输入流到输出流 | |
copyLarge(InputStream, OutputStream) | 大文件拷贝 | |
copy(InputStream, Writer, String) | 拷贝到 Writer | |
copy(Reader, OutputStream, String) | Reader 拷贝到输出流 | |
closeQuietly(InputStream) | 安静关闭流 | 不抛异常 |
closeQuietly(OutputStream) | 安静关闭流 | |
closeQuietly(Reader) | 安静关闭 Reader | |
closeQuietly(Writer) | 安静关闭 Writer | |
closeQuietly(Closeable...) | 批量安静关闭 | |
close(Closeable) | 关闭流(Java 7+推荐) | |
read(InputStream, byte[]) | 读取到字节数组 | |
readFully(InputStream, byte[]) | 完全读取 | |
skip(InputStream, long) | 跳过指定字节 | |
skipFully(InputStream, long) | 完全跳过 |
java
import org.apache.commons.io.IOUtils;
import java.io.*;
import java.util.List;
public class IOUtilsDemo {
public static void main(String[] args) throws IOException {
InputStream is = new FileInputStream("file.txt");
// 输入流转字符串
String content = IOUtils.toString(is, "UTF-8");
// 输入流转字节数组
byte[] bytes = IOUtils.toByteArray(is);
// 按行读取
List<String> lines = IOUtils.readLines(is, "UTF-8");
// 字符串转输入流
InputStream stringStream = IOUtils.toInputStream("Hello", "UTF-8");
// 拷贝流
OutputStream os = new FileOutputStream("copy.txt");
IOUtils.copy(is, os);
// 大文件拷贝
FileInputStream fis = new FileInputStream("bigfile.zip");
FileOutputStream fos = new FileOutputStream("copy.zip");
IOUtils.copyLarge(fis, fos);
// 安静关闭(不抛异常,适合 finally 块)
IOUtils.closeQuietly(is);
IOUtils.closeQuietly(os);
// 批量关闭
IOUtils.closeQuietly(is, os, reader, writer);
// Java 7+ 推荐方式
IOUtils.close(is);
}
}3.3 FilenameUtils — 文件名操作工具类
| 方法 | 说明 | 示例 |
|---|---|---|
getName(String) | 获取文件名 | getName("a/b/c.txt") → "c.txt" |
getBaseName(String) | 获取文件名(不含扩展名) | getBaseName("c.txt") → "c" |
getExtension(String) | 获取扩展名 | getExtension("c.txt") → "txt" |
getPath(String) | 获取路径部分 | getPath("a/b/c.txt") → "a/b/" |
getFullPath(String) | 获取完整路径 | |
getPrefix(String) | 获取前缀 | getPrefix("C:/a/b") → "C:/" |
removeExtension(String) | 移除扩展名 | removeExtension("c.txt") → "c" |
concat(String, String) | 安全拼接路径 | concat("/a/b", "c.txt") → "/a/b/c.txt" |
separatorsToUnix(String) | 分隔符转 Unix 风格 | separatorsToUnix("C:\\a\\b") → "C:/a/b" |
separatorsToWindows(String) | 分隔符转 Windows 风格 | |
separatorsToSystem(String) | 分隔符转系统风格 | |
normalize(String) | 规范化路径 | normalize("/a/b/../c") → "/a/c" |
normalizeNoEndSeparator(String) | 规范化(无末尾分隔符) | |
wildcardMatch(String, String) | 通配符匹配 | wildcardMatch("file.txt", "*.txt") → true |
isExtension(String, String...) | 判断扩展名 | isExtension("a.txt", "txt", "doc") → true |
java
import org.apache.commons.io.FilenameUtils;
public class FilenameUtilsDemo {
public static void main(String[] args) {
String path = "C:/Users/admin/documents/report.pdf";
System.out.println(FilenameUtils.getName(path)); // "report.pdf"
System.out.println(FilenameUtils.getBaseName(path)); // "report"
System.out.println(FilenameUtils.getExtension(path)); // "pdf"
System.out.println(FilenameUtils.getPath(path)); // "Users/admin/documents/"
// 移除扩展名
String noExt = FilenameUtils.removeExtension("image.png"); // "image"
// 安全拼接路径
String fullPath = FilenameUtils.concat("/home/user", "file.txt");
// "/home/user/file.txt"
// 路径规范化
String normalized = FilenameUtils.normalize("/a/b/../c/./d");
// "/a/c/d"
// 通配符匹配
boolean match = FilenameUtils.wildcardMatch("log_20240115.txt", "log_*.txt"); // true
// 判断扩展名
boolean isImage = FilenameUtils.isExtension("photo.jpg", "jpg", "png", "gif"); // true
// 转换分隔符
String unixPath = FilenameUtils.separatorsToUnix("C:\\Users\admin"); // "C:/Users/admin"
}
}4. Commons Collections4
4.1 CollectionUtils — 集合工具类
| 方法 | 说明 | 示例 |
|---|---|---|
isEmpty(Collection) | 判断集合为空 | |
isNotEmpty(Collection) | 判断集合非空 | |
size(Collection) | 安全获取大小 | size(null) → 0 |
sizeIsEmpty(Collection) | 判断是否为空 | |
containsAny(Collection, Collection) | 判断是否包含任意共同元素 | |
containsAll(Collection, Collection) | 判断是否包含全部 | |
intersection(Collection, Collection) | 交集 | |
union(Collection, Collection) | 并集 | |
subtract(Collection, Collection) | 差集 | |
disjunction(Collection, Collection) | 对称差集 | |
filter(Collection, Predicate) | 过滤集合 | |
select(Collection, Predicate) | 选择符合条件的元素 | |
selectRejected(Collection, Predicate) | 选择不符合的元素 | |
transform(Collection, Transformer) | 转换集合元素 | |
collect(Collection, Transformer) | 收集转换结果 | |
find(Collection, Predicate) | 查找第一个符合条件的 | |
countMatches(Collection, Predicate) | 统计匹配数量 | |
exists(Collection, Predicate) | 是否存在匹配 | |
addIgnoreNull(Collection, Object) | 忽略 null 添加 | |
addAll(Collection, Iterator) | 添加 Iterator 元素 | |
get(Collection, int) | 安全获取元素 | get(null, 0) → null |
getCardinalityMap(Collection) | 获取元素出现次数 Map | |
unmodifiableCollection(Collection) | 不可修改集合 | |
predicatedCollection(Collection, Predicate) | 带验证的集合 | |
transformingCollection(Collection, Transformer) | 自动转换集合 | |
synchronizedCollection(Collection) | 线程安全集合 |
java
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.Predicate;
import org.apache.commons.collections4.Transformer;
import java.util.*;
public class CollectionUtilsDemo {
public static void main(String[] args) {
List<Integer> list1 = Arrays.asList(1, 2, 3, 4, 5);
List<Integer> list2 = Arrays.asList(4, 5, 6, 7, 8);
// 空值判断
System.out.println(CollectionUtils.isEmpty(list1)); // false
System.out.println(CollectionUtils.isEmpty(null)); // true
// 集合运算
Collection<Integer> intersection = CollectionUtils.intersection(list1, list2); // [4, 5]
Collection<Integer> union = CollectionUtils.union(list1, list2); // [1,2,3,4,5,6,7,8]
Collection<Integer> subtract = CollectionUtils.subtract(list1, list2); // [1, 2, 3]
Collection<Integer> disjunction = CollectionUtils.disjunction(list1, list2); // [1,2,3,6,7,8]
// 过滤
Predicate<Integer> evenPredicate = n -> n % 2 == 0;
Collection<Integer> evenNumbers = CollectionUtils.select(list1, evenPredicate); // [2, 4]
// 查找
Integer first = CollectionUtils.find(list1, n -> n > 3); // 4
// 统计
int count = CollectionUtils.countMatches(list1, n -> n > 2); // 3
// 转换
Transformer<Integer, String> toString = n -> "Number: " + n;
Collection<String> strings = CollectionUtils.collect(list1, toString);
// ["Number: 1", "Number: 2", ...]
// 安全获取
Integer val = CollectionUtils.get(list1, 10); // null (不会抛 IndexOutOfBounds)
// 统计元素出现次数
List<String> words = Arrays.asList("a", "b", "a", "c", "a");
Map<String, Integer> cardinality = CollectionUtils.getCardinalityMap(words);
// {"a": 3, "b": 1, "c": 1}
// 添加时忽略 null
List<String> list = new ArrayList<>();
CollectionUtils.addIgnoreNull(list, "a"); // 添加成功
CollectionUtils.addIgnoreNull(list, null); // 忽略
}
}4.2 MapUtils — Map 工具类
| 方法 | 说明 | 示例 |
|---|---|---|
isEmpty(Map) | 判断 Map 为空 | |
isNotEmpty(Map) | 判断 Map 非空 | |
size(Map) | 安全获取大小 | |
getString(Map, Object) | 安全获取 String | getString(map, "key") |
getString(Map, Object, String) | 带默认值的获取 | |
getInteger(Map, Object) | 安全获取 Integer | |
getInteger(Map, Object, Integer) | 带默认值的获取 | |
getLong(Map, Object) | 安全获取 Long | |
getDouble(Map, Object) | 安全获取 Double | |
getBoolean(Map, Object) | 安全获取 Boolean | |
getObject(Map, Object) | 安全获取 Object | |
getObject(Map, Object, Object) | 带默认值的获取 | |
safeAddToMap(Map, Object, Object) | 安全添加 | |
putAll(Map, Object[]) | 批量添加 | |
fixedSizeMap(Map) | 固定大小 Map | |
lazyMap(Map, Factory) | 懒加载 Map | |
orderedMap(Map) | 有序 Map | |
synchronizedMap(Map) | 线程安全 Map | |
unmodifiableMap(Map) | 不可修改 Map | |
predicatedMap(Map, Predicate, Predicate) | 带验证的 Map | |
transformedMap(Map, Transformer, Transformer) | 自动转换 Map | |
multiValueMap(Map) | 多值 Map | |
invertMap(Map) | 键值反转 | invertMap({"a":1}) → {1:"a"} |
toProperties(Map) | 转 Properties | |
toMap(ResourceBundle) | ResourceBundle 转 Map |
java
import org.apache.commons.collections4.MapUtils;
import java.util.*;
public class MapUtilsDemo {
public static void main(String[] args) {
Map<String, Object> map = new HashMap<>();
map.put("name", "Tom");
map.put("age", 25);
map.put("score", 85.5);
map.put("vip", true);
// 空值判断
System.out.println(MapUtils.isEmpty(map)); // false
System.out.println(MapUtils.isEmpty(null)); // true
// 安全获取(避免 null 和类型转换异常)
String name = MapUtils.getString(map, "name"); // "Tom"
String unknown = MapUtils.getString(map, "unknown"); // null
String withDefault = MapUtils.getString(map, "unknown", "default"); // "default"
Integer age = MapUtils.getInteger(map, "age"); // 25
Integer badAge = MapUtils.getInteger(map, "name"); // null (不会抛异常)
Integer defAge = MapUtils.getInteger(map, "name", 0); // 0
Double score = MapUtils.getDouble(map, "score"); // 85.5
Boolean vip = MapUtils.getBoolean(map, "vip"); // true
// 键值反转
Map<String, Integer> original = new HashMap<>();
original.put("a", 1);
original.put("b", 2);
Map<Integer, String> inverted = MapUtils.invertMap(original);
// {1="a", 2="b"}
// 转 Properties
Properties props = MapUtils.toProperties(map);
// 固定大小 Map
Map<String, String> fixed = MapUtils.fixedSizeMap(new HashMap<>());
// fixed.put("new", "value"); // 会抛异常
// 懒加载 Map
Map<String, List<String>> lazyMap = MapUtils.lazyMap(new HashMap<>(), () -> new ArrayList<>());
lazyMap.get("key").add("value"); // 自动创建 ArrayList
}
}5. 最佳实践总结
5.1 字符串处理优先使用 StringUtils
java
// ❌ 不推荐:手动判空,容易 NPE
if (str != null && !str.isEmpty() && !str.trim().isEmpty()) { ... }
// ✅ 推荐:StringUtils 一行搞定
if (StringUtils.isNotBlank(str)) { ... }
// ❌ 不推荐:手动分割,处理空值麻烦
String[] parts = str.split(","); // 可能 NPE
// ✅ 推荐:StringUtils 安全分割
String[] parts = StringUtils.split(str, ","); // null-safe5.2 文件操作优先使用 FileUtils
java
// ❌ 不推荐:手动处理流,代码冗长且易遗漏关闭
BufferedReader br = null;
try {
br = new BufferedReader(new FileReader("file.txt"));
String line;
while ((line = br.readLine()) != null) { ... }
} finally {
if (br != null) br.close();
}
// ✅ 推荐:FileUtils 一行读取
List<String> lines = FileUtils.readLines(new File("file.txt"), "UTF-8");
// ❌ 不推荐:手动拷贝文件
Files.copy(source.toPath(), dest.toPath());
// ✅ 推荐:FileUtils 自动处理属性
FileUtils.copyFile(source, dest, true); // 保留文件属性5.3 集合操作优先使用 CollectionUtils / MapUtils
java
// ❌ 不推荐:手动判空
if (list != null && !list.isEmpty()) { ... }
// ✅ 推荐:CollectionUtils
if (CollectionUtils.isNotEmpty(list)) { ... }
// ❌ 不推荐:手动从 Map 取值并转换
Object obj = map.get("key");
String val = obj != null ? obj.toString() : "default";
// ✅ 推荐:MapUtils 安全获取
String val = MapUtils.getString(map, "key", "default");5.4 安全转换使用 NumberUtils
java
// ❌ 不推荐:直接转换可能抛异常
int num = Integer.parseInt(userInput);
// ✅ 推荐:NumberUtils 安全转换
int num = NumberUtils.toInt(userInput, 0); // 失败返回 05.5 流操作使用 IOUtils
java
// ❌ 不推荐:手动关闭流,容易遗漏
is.close();
os.close();
// ✅ 推荐:IOUtils 安静关闭
IOUtils.closeQuietly(is, os);
// ✅ 推荐:Java 7+ try-with-resources + IOUtils
try (InputStream is = new FileInputStream("file.txt")) {
String content = IOUtils.toString(is, "UTF-8");
} catch (IOException e) {
// 处理异常
}附录:常用工具类速查表
| 工具类 | 包路径 | 主要用途 |
|---|---|---|
StringUtils | org.apache.commons.lang3 | 字符串操作 |
ArrayUtils | org.apache.commons.lang3 | 数组操作 |
ObjectUtils | org.apache.commons.lang3 | 对象操作 |
NumberUtils | org.apache.commons.lang3.math | 数字转换 |
DateUtils | org.apache.commons.lang3.time | 日期计算 |
DateFormatUtils | org.apache.commons.lang3.time | 日期格式化 |
RandomStringUtils | org.apache.commons.lang3 | 随机字符串 |
FileUtils | org.apache.commons.io | 文件操作 |
IOUtils | org.apache.commons.io | 流操作 |
FilenameUtils | org.apache.commons.io | 文件名操作 |
CollectionUtils | org.apache.commons.collections4 | 集合操作 |
MapUtils | org.apache.commons.collections4 | Map 操作 |