Apache Commons Codec 快速入门与集成示例

Commons Codec 1.23.0 快速入门:Maven 与手动 jar 两种引入,示例覆盖 Base64 三变体与流式、DigestUtils 摘要互验、Hex、URLCodec、Soundex、Base32,JDK 17 实测。

Apache Commons CodecApache Commons Codec2026/10/13

Apache Commons Codec 快速入门与集成示例

目标:用一篇文档完成 Apache Commons Codec 1.23.0 的依赖引入与核心 API 上手——一个覆盖 Base64 三变体与流式 API、DigestUtils 摘要与命令行互验、Hex、URLCodec、Soundex/Metaphone、Base32 的示例类可整体复制运行,已在 Ubuntu 22.04(OpenJDK 17.0.20.1、Maven 3.6.3)实测通过。

一、环境信息

  • 操作系统:Ubuntu 22.04(jammy),x86_64
  • JDK:OpenJDK 17.0.20.1(Codec 1.23.0 字节码为 Java 8,JDK 8+ 均可运行本篇示例)
  • 构建工具:Apache Maven 3.6.3(仅 3.1 节方案需要)
  • 组件版本:Apache Commons Codec 1.23.0(downloads.apache.org 当前最新,2026-10 实测;jar 440773 字节)
  • 实验目录:/opt/lab/codec-maven(Maven 工程)与 /opt/lab/codec-manual(手动 jar)
  • 执行用户:root

二、前置条件

只需 JDK 8+ 与网络可达。JDK 核验:

java -version 2>&1 | head -1

回显(实测):

openjdk version "17.0.20.1" 2026-08-18

网络与官方站核验:

curl -sI https://downloads.apache.org/commons/codec/ | head -1

回显(实测):

HTTP/1.1 200 OK

两条核验通过即可开始。

三、依赖引入

Codec 无传递依赖、单 jar 即可用,因此引入方式只有两种,均给出可独立执行的命令与回显。

3.1 方式一:Maven 依赖(推荐)

在工程 pom.xml 中加入依赖:

<dependency>
  <groupId>commons-codec</groupId>
  <artifactId>commons-codec</artifactId>
  <version>1.23.0</version>
</dependency>

参数说明:groupId/artifactId 固定为 commons-codec:commons-codec(Maven 中央仓库坐标);version 用 1.23.0(官方最新,实测可拉取)。首次编译自动下载到本地仓库:

cd /opt/lab/codec-maven && mvn -q compile 2>/dev/null; ls ~/.m2/repository/commons-codec/commons-codec/1.23.0/

回显(实测):

commons-codec-1.23.0.jar  commons-codec-1.23.0.pom  _remote.repositories

Gradle 工程对应写法为 implementation 'commons-codec:commons-codec:1.23.0',坐标一致。

3.2 方式二:手动下载 jar(java -cp 直跑)

官方发行包下载、校验、解压三连(命令可独立执行):

mkdir -p /opt/lab/codec-manual/lib && cd /opt/lab/codec-manual && wget -q https://downloads.apache.org/commons/codec/binaries/commons-codec-1.23.0-bin.tar.gz && wget -q https://downloads.apache.org/commons/codec/binaries/commons-codec-1.23.0-bin.tar.gz.sha512 && printf '%s  %s\n' "$(cat commons-codec-1.23.0-bin.tar.gz.sha512)" commons-codec-1.23.0-bin.tar.gz | sha512sum -c - && tar xzf commons-codec-1.23.0-bin.tar.gz && cp commons-codec-1.23.0/commons-codec-1.23.0.jar lib/

回显(实测):

commons-codec-1.23.0-bin.tar.gz: OK
ls -l /opt/lab/codec-manual/lib/

回显(实测):

total 432
-rw-r--r-- 1 root root 440773 Oct 13 04:12 commons-codec-1.23.0.jar

校验 OK 且主 jar 就位,后续示例直接 java -cp classes:lib/commons-codec-1.23.0.jar 运行。

四、核心 API 速览

先看包结构,建立「什么需求找哪个包」的映射:

jar tf /opt/lab/codec-manual/lib/commons-codec-1.23.0.jar | head -12

回显(实测):

META-INF/
META-INF/MANIFEST.MF
org/
org/apache/
org/apache/commons/
org/apache/commons/codec/
org/apache/commons/codec/binary/
org/apache/commons/codec/cli/
org/apache/commons/codec/digest/
org/apache/commons/codec/language/
org/apache/commons/codec/language/bm/
org/apache/commons/codec/net/
包代表类解决什么问题
binaryBase64、Base32、Hex、BinaryCodec字节与文本互转(Base64/Base32/十六进制/二进制位串)
digestDigestUtils、HmacUtils摘要与 HMAC(MD5/SHA 族一键求值)
languageSoundex、Metaphone英文姓名语音编码(发音相近判断)
netURLCodecURL percent 编解码

解读:日常使用频率最高的是 binary.Base64 与 digest.DigestUtils,本篇第五节的示例按「Base64 → 摘要 → Hex → URL → 语音 → Base32」顺序展开,一个类跑通全部。

五、集成示例:一个类跑通核心 API

示例类 QuickStart.java 覆盖六组 API,代码整体复制即可运行;本节给出全文、运行命令与逐段解读。

5.1 完整示例代码

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import org.apache.commons.codec.binary.Base32;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.codec.binary.Base64InputStream;
import org.apache.commons.codec.binary.BinaryCodec;
import org.apache.commons.codec.binary.Hex;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.codec.language.Metaphone;
import org.apache.commons.codec.language.Soundex;
import org.apache.commons.codec.net.URLCodec;

public class QuickStart {
    public static void main(String[] args) throws Exception {
        String jar = args.length > 0 ? args[0] : "lib/commons-codec-1.23.0.jar";
        String tarball = args.length > 1 ? args[1] : "commons-codec-1.23.0-bin.tar.gz";

        System.out.println("[1] Base64 标准 / URL-safe / MIME");
        String text = "Apache Commons Codec";
        byte[] raw = text.getBytes(StandardCharsets.UTF_8);
        System.out.println("encodeBase64String: " + Base64.encodeBase64String(raw));
        System.out.println("decodeBase64 回   : " + new String(Base64.decodeBase64(Base64.encodeBase64String(raw)), StandardCharsets.UTF_8));
        String unsafe = "subject=??&tag=a+b";
        System.out.println("标准  : " + Base64.encodeBase64String(unsafe.getBytes(StandardCharsets.UTF_8)));
        System.out.println("URLsafe: " + Base64.encodeBase64URLSafeString(unsafe.getBytes(StandardCharsets.UTF_8)));
        Base64 mime = Base64.builder().setLineLength(16).setLineSeparator((byte) '\n').get();
        System.out.println("MIME  :");
        System.out.println(new String(mime.encode(raw), StandardCharsets.US_ASCII).trim());

        System.out.println("[2] Base64 流式");
        byte[] buf = new byte[1024];
        int n;
        Base64InputStream enc = Base64InputStream.builder().setInputStream(new ByteArrayInputStream(raw)).setEncode(true).get();
        ByteArrayOutputStream eo = new ByteArrayOutputStream();
        while ((n = enc.read(buf)) > 0) { eo.write(buf, 0, n); }
        enc.close();
        System.out.println("流式编码: " + new String(eo.toByteArray(), StandardCharsets.US_ASCII).trim());
        Base64InputStream dec = Base64InputStream.builder().setInputStream(new ByteArrayInputStream(eo.toByteArray())).get();
        ByteArrayOutputStream dout = new ByteArrayOutputStream();
        while ((n = dec.read(buf)) > 0) { dout.write(buf, 0, n); }
        dec.close();
        System.out.println("流式解码: " + new String(dout.toByteArray(), StandardCharsets.UTF_8));

        System.out.println("[3] DigestUtils 字符串摘要");
        String s = "hello commons codec";
        System.out.println("md5Hex    = " + DigestUtils.md5Hex(s));
        System.out.println("sha1Hex   = " + DigestUtils.sha1Hex(s));
        System.out.println("sha256Hex = " + DigestUtils.sha256Hex(s));
        System.out.println("sha512Hex = " + DigestUtils.sha512Hex(s));

        System.out.println("[4] DigestUtils 文件摘要");
        InputStream in = new FileInputStream(tarball);
        System.out.println("sha512Hex(file) = " + DigestUtils.sha512Hex(in));
        in.close();

        System.out.println("[5] Hex 与 BinaryCodec");
        System.out.println("encodeHexString(\"AB\") = " + Hex.encodeHexString("AB".getBytes(StandardCharsets.UTF_8)));
        System.out.println("decodeHex(\"4142\")     = " + new String(Hex.decodeHex("4142".toCharArray()), StandardCharsets.UTF_8));
        BinaryCodec bc = new BinaryCodec();
        System.out.println("toAsciiString(01000001) = " + bc.toAsciiString(bc.toByteArray("01000001")));

        System.out.println("[6] URLCodec");
        URLCodec uc = new URLCodec("UTF-8");
        String q = "https://example.com/search?q=java 编解码&x=中";
        String e = uc.encode(q);
        System.out.println("encode: " + e);
        System.out.println("decode: " + uc.decode(e));

        System.out.println("[7] Soundex / Metaphone");
        String[] names = {"Robert", "Rupert", "Ashcraft", "Tymczak", "Pfister", "Honeyman"};
        Soundex sx = new Soundex();
        Metaphone mp = new Metaphone();
        for (String name : names) {
            System.out.printf("%-9s Soundex=%-5s Metaphone=%-5s%n", name, sx.soundex(name), mp.metaphone(name));
        }
        System.out.println("soundex(Robert)==soundex(Rupert): " + sx.soundex("Robert").equals(sx.soundex("Rupert")));

        System.out.println("[8] Base32");
        Base32 b32 = new Base32();
        String b32e = b32.encodeToString(raw);
        System.out.println("Base32: " + b32e);
        System.out.println("decode: " + new String(b32.decode(b32e), StandardCharsets.UTF_8));
    }
}

代码要点:所有字符串转字节都显式用 StandardCharsets.UTF_8,避免平台默认编码差异;流式 API 用 1.23 的 Builder(Base64InputStream.builder().setInputStream(new ByteArrayInputStream(raw)).setEncode(true).get());示例依赖的 commons-codec-1.23.0-bin.tar.gz 正是 3.2 节下载的发行包,用它同时演示「文件摘要」。

5.2 编译与运行(完整实测回显)

手动 jar 方式(与 3.2 节衔接):

cd /opt/lab/codec-manual && mkdir -p classes && javac -encoding UTF-8 -cp lib/commons-codec-1.23.0.jar -d classes src/QuickStart.java && LANG=C.UTF-8 java -cp classes:lib/commons-codec-1.23.0.jar QuickStart

回显(实测):

[1] Base64 标准 / URL-safe / MIME
encodeBase64String: QXBhY2hlIENvbW1vbnMgQ29kZWM=
decodeBase64 回   : Apache Commons Codec
标准  : c3ViamVjdD0/PyZ0YWc9YSti
URLsafe: c3ViamVjdD0_PyZ0YWc9YSti
MIME  :
QXBhY2hlIENvbW1v
bnMgQ29kZWM=
[2] Base64 流式
流式编码: QXBhY2hlIENvbW1vbnMgQ29kZWM=
流式解码: Apache Commons Codec
[3] DigestUtils 字符串摘要
md5Hex    = 0de51781c71760acea105104c0460127
sha1Hex   = cb90638848312bf8a878880f3c402aa05b4017e9
sha256Hex = 194a3449ab8c2a0649f03e6b73fd919d08fcd0730dcbd5269c998ff3a4b0d8ca
sha512Hex = cffb89896132f7706636fd8d5c142b2ddec741efde425f9619e01b2d39f2c0b411e7e227af3b93bd0660337210a6dedf6af46e3944e3db7ac102663f6ff645b0
[4] DigestUtils 文件摘要
sha512Hex(file) = 34a8cb4bafd3bb56fed56f1609b9c45f8cc25c31d7fdc9fca8df498d9b73efb4b8636b5f8a1c7d6439cca200b35a991867287b4ca14159af8cef4ca56a04559a
[5] Hex 与 BinaryCodec
encodeHexString("AB") = 4142
decodeHex("4142")     = AB
toAsciiString(01000001) = 01000001
[6] URLCodec
encode: https%3A%2F%2Fexample.com%2Fsearch%3Fq%3Djava+%E7%BC%96%E8%A7%A3%E7%A0%81%26x%3D%E4%B8%AD
decode: https://example.com/search?q=java 编解码&x=中
[7] Soundex / Metaphone
Robert    Soundex=R163  Metaphone=RBRT
Rupert    Soundex=R163  Metaphone=RPRT
Ashcraft  Soundex=A261  Metaphone=AXKR
Tymczak   Soundex=T522  Metaphone=TMKS
Pfister   Soundex=P236  Metaphone=PFST
Honeyman  Soundex=H555  Metaphone=HNMN
soundex(Robert)==soundex(Rupert): true
[8] Base32
Base32: IFYGCY3IMUQEG33NNVXW44ZAINXWIZLD
decode: Apache Commons Codec

💡 技术拓展:Base64 常见变体对比——

变体字母表差异换行补位符典型场景
标准(RFC 4648)A-Z a-z 0-9 + /否=HTTP Basic、常规二进制转文本
URL-safe- _ 替换 + /否无URL 参数、Cookie、JWT
MIME(RFC 2045)同标准每 76 字符 CRLF=邮件正文附件

示例 [1] 三种形态各实测一次:URL-safe 输出把标准形态中的 / 换成 _ 且不带补位 =;MIME 组合用 Builder 设 16 字符行宽每行换行。选型看「密文去哪」:进 URL 用 URL-safe,进邮件用 MIME 分行,其余用标准。

5.3 Base64 段解读

  • 标准:encodeBase64String 编码、decodeBase64 还原,输入输出闭环一致;
  • URL-safe:原文含 +、?、&,标准表输出 c3ViamVjdD0/PyZ0YWc9YSti,URL-safe 输出 c3ViamVjdD0_PyZ0YWc9YSti——逐字符对比可见差异仅在 / 换成 _ 一处,且末尾没有补位 =;
  • MIME:setLineLength(16) 使每 16 个字符换行,解码侧 decodeBase64 直接吃带换行密文无需预处理;
  • 流式:Base64InputStream 以「读到即转换」方式工作,setEncode(true) 编码、默认解码,读完 close() 刷出尾块——大文件转码内存占用恒定。

5.4 摘要段解读与命令行互验

💡 技术拓展:摘要算法横向对比——

算法摘要长度hex 长度(本节实测)安全现状适用
MD5128 位32已可构造碰撞非安全校验、旧协议兼容
SHA-1160 位40已实质攻破遗留系统(如 git 对象)
SHA-256256 位64目前安全通用推荐
SHA-512512 位128目前安全高安全、官方发行包校验

示例 [3][4] 四算法同跑便于直观对比长度;生产选型 SHA-256 起步,校验发行包跟随官方 SHA-512。

最关键的实测验证:示例 [4] 的文件摘要值与系统命令逐字符一致——

cd /opt/lab/codec-manual && sha512sum commons-codec-1.23.0-bin.tar.gz

回显(实测):

34a8cb4bafd3bb56fed56f1609b9c45f8cc25c31d7fdc9fca8df498d9b73efb4b8636b5f8a1c7d6439cca200b35a991867287b4ca14159af8cef4ca56a04559a  commons-codec-1.23.0-bin.tar.gz
cd /opt/lab/codec-manual && openssl dgst -sha256 commons-codec-1.23.0-bin.tar.gz

回显(实测):

SHA2-256(commons-codec-1.23.0-bin.tar.gz)= 32af8585924eda935c05e171d5f96c2ef8c3f108ef05f96080253dc68f800816

sha512sum 与示例 [4] 的 sha512Hex(file) 完全相同,且正是官方 .sha512 文件里的值;openssl dgst -sha256 与示例 [3][4] 的 sha256 值一致。字符串摘要同理:printf 'hello commons codec' | md5sum 实测输出 0de51781c71760acea105104c0460127,与示例 [3] 的 md5Hex 相同(注意用 printf 而非 echo,后者多一个换行字节)。

5.5 Hex、URLCodec 段解读

  • Hex:encodeHexString 默认小写,"AB" 编码为 4142;decodeHex 接受 char[],奇数长度或非法字符抛 DecoderException;
  • BinaryCodec:把 01000001 位串还原为一个字节 0x41(即字母 A),适合位级协议调试;
  • URLCodec:空格编码为 +、中文按 UTF-8 编为 %E4%B8%AD,与 application/x-www-form-urlencoded 规则一致;若与前端 encodeURIComponent(空格为 %20)对接,需注意这一差异或自行替换。

5.6 语音编码与 Base32 段解读

💡 技术拓展:英文姓名语音算法不止一种,常见对比——

算法编码长度特点适用
Soundex固定 4 位(字母+3 数字)首字母保留,辅音归并成数字老牌标准,客服检索姓氏
Metaphone变长(默认 4)考虑英文发音规则(如 PH→F)拼写纠错、模糊匹配
RefinedSoundex变长更细的归并粒度需要更少误合并的场景
Beider-Morse变长支持多语言(language.bm 包)多语种姓名

示例 [7] 同时输出 Soundex 与 Metaphone 两列便于对照;本文场景(英文姓名去重)两者均可用,示例采用 Soundex 做相似判定、Metaphone 做辅助核对。

示例数据解读:Robert 与 Rupert 的 Soundex 同为 R163(发音等价是 Soundex 的经典用例);Ashcraft 归并为 A261(SC 合并);Metaphone 把 Smith/Smyth 判为同音(isMetaphoneEqual 实测为 true)。Base32 段:20 字节输入编码出 32 个字符(5 比特/字符,恰好整除无补位),标准字母表不含 0、1、8、9,解码闭环一致。

六、注意事项

  • 摘要选型安全第一:MD5/SHA-1 只用于兼容存量协议,新代码一律 SHA-256 起步;口令存储应使用加盐摘要或专用算法(Codec 不提供 bcrypt 等口令哈希)。
  • String 入参固定 UTF-8:DigestUtils.md5Hex(String) 等方法按 UTF-8 取字节,非 UTF-8 数据需先自行 getBytes(charset) 再走 byte[] 重载。
  • 流式 API 必须 close:Base64OutputStream 不关闭会丢失最后不足块的数据。
  • URLCodec 是表单编码规则(空格为 +),与 RFC 3986 的 %20 风格不同,跨端对接先统一规则。
  • Base64 的 URL-safe 形态不补 =:与要求补位的对端对接时改用标准表或约定补齐规则。
  • 运行环境 locale 非 UTF-8 时中文输出会变 ?:命令行加 LANG=C.UTF-8,编译加 -encoding UTF-8。

七、参考链接

  1. Apache Commons Codec 用户指南:https://commons.apache.org/proper/commons-codec/userguide.html
  2. Apache Commons Codec 官方下载:https://downloads.apache.org/commons/codec/
  3. Maven 中央仓库 commons-codec:https://mvnrepository.com/artifact/commons-codec/commons-codec
  4. RFC 4648(Base64/Base32 标准):https://datatracker.ietf.org/doc/html/rfc4648
  5. Soundex 算法说明:https://commons.apache.org/proper/commons-codec/apidocs/org/apache/commons/codec/language/Soundex.html