📋 目录
一、工具类功能
把按行组织好的数据拼成符合 RFC 4180 的 CSV 并写入指定目录,父目录自动创建、同名文件覆盖、字符集可选,字段里的逗号、双引号与换行都会被正确转义。
二、所需环境
JDK 17或以上
三、方法与调用示例(按需调用)
🔢 方法序号:1
🎯 方法用途:
- 按 UTF-8 把已经拼好的 CSV 记录写到指定目录,返回文件路径
- 导出对账文件、报表给下游系统取走时用这一版
🧩 方法定义:public static Path writeCsv(String dirPath, String fileName, Collection<String> lines) throws IOException
🗣️ 入参解释:public static Path writeCsv(目录字符串, 文件名, 行集合)
📤 返回值解释:Path,写出后的文件路径
💡 边界口径:
- 每个元素就是一条记录,方法只负责在记录之间插换行,不猜内容
- 行分隔固定
\n,最后一行不带换行,同样数据在 Windows 与 Linux 上字节一致 fileName只允许纯文件名,含/、\、:或..一律拒绝,防目录穿越- 目录不存在会自动创建;校验不过时不会落地文件
- 同名文件直接覆盖,不是追加;真实读写失败按
IOException原样抛
🧪 方法示例:
writeCsv(outDir, "orders-utf8.csv", lines)写完再判存在,拿到true- 文件字节数拿到
126 字节,记录之间是 3 个 LF 且最后一行不带换行 - 全文拿到
订单号,客户,金额,备注[LF]ORD20261005000123,张三,128,"备注,带逗号"[LF]ORD20261005000456,李四,66,"多行[LF]第二行" - 文件名传
../evil.csv抛fileName 只能是文件名,不能包含路径分隔符或 ..: ../evil.csv - 行集合传空集合抛
lines 不能为空,其中一行是 null 抛第2行内容为null,空行请传空字符串 - 前面几次失败的调用之后,目录里现存
3 个 csv,校验不过没落地
🔢 方法序号:2
🎯 方法用途:
- 目录用
Path传的同一写入口,仍按 UTF-8 - 用
Paths.get、Path.resolve组织输出目录的工程里少一次字符串转换
🧩 方法定义:public static Path writeCsv(Path dir, String fileName, Collection<String> lines) throws IOException
🗣️ 入参解释:public static Path writeCsv(目录Path, 文件名, 行集合)
📤 返回值解释:Path,写出后的文件路径
💡 边界口径:
- 多级父目录一次建齐,不需要先
Files.createDirectories - 与字符串目录版同一套校验与写出规则
dir传 null 抛NullPointerException,消息点出参数名
🧪 方法示例:
writeCsv(deepDir, "orders-path.csv", lines)之后判存在,拿到truewriteCsv(null, "a.csv", lines)抛dir 不能为null
🔢 方法序号:3
🎯 方法用途:
- 指定字符集写出 CSV,给只能读 GBK 的老系统或对端用
- 要控制 BOM、编码宽度这类差异时走这一版
🧩 方法定义:public static Path writeCsv(Path dir, String fileName, Collection<String> lines, Charset charset) throws IOException
🗣️ 入参解释:public static Path writeCsv(目录Path, 文件名, 行集合, 字符集)
📤 返回值解释:Path,写出后的文件路径
💡 边界口径:
charset传 null 按 UTF-8 走,与三参版产出完全一致的字节- 中文内容换字符集字节数会变,GBK 比 UTF-8 少
- Excel 双击打开无 BOM 的 UTF-8 文件可能中文乱码,要直开就传带 BOM 的字符集或改用 Excel 导出
- 校验与写出规则同两参版
🧪 方法示例:
- 同一份内容 GBK 写出拿到
103 字节,UTF-8 是126 字节 - 字符集传 null 与 UTF-8 版本比对,拿到
字节一致 true - GBK 文件按 GBK 读回首行拿到
订单号,客户,金额,备注 - 同名文件再写一次是覆盖,字节从
126变成21
🔢 方法序号:4
🎯 方法用途:
- 把一行字段按 RFC 4180 拼成一条 CSV 记录,不含换行
- 字段里有逗号、引号、换行、首尾空白时必须先经它,别自己拼字符串
🧩 方法定义:public static String formatRow(Collection<?> fields)
🗣️ 入参解释:public static String formatRow(一行字段)
📤 返回值解释:String,一条完整的 CSV 记录
💡 边界口径:
- 字段按迭代顺序输出,
null字段写成空串,数字与布尔取toString - 需要转义的字段自动加引号,内部双引号翻倍
- 入参集合本身不被改动
- 空集合与 null 入参都返回空串,不抛异常
🧪 方法示例:
formatRow(fields)拿到ORD20261005000123,张三,128,"备注,带逗号",,末尾的 null 字段是空串- 集合入参
formatRow(tagFields)拿到vip,"加急,特急" formatRow(List.of("备注", multiLine))拿到正确输出 [备注,"多行[LF]第二行"],裸拼的那一份会被读成两条记录- 空集合与 null 入参分别拿到
[]、[],原集合仍是[ORD20261005000123, 张三, 128, 备注,带逗号, null]
🔢 方法序号:5
🎯 方法用途:
- 单个字段做 CSV 转义,需要时才加引号
- 自己在拼整行、或者要把外部字段安全塞进 CSV 时用
🧩 方法定义:public static String escape(Object value)
🗣️ 入参解释:public static String escape(单个字段)
📤 返回值解释:String,转义后的字段文本
💡 边界口径:
- 含逗号、双引号、换行的字段加引号,内部双引号翻倍
- 首尾带空白的字段也加引号,否则会被解析器裁掉;中间空白不用加
null写成空串,数字与布尔取toString- 普通字段原样返回,不加多余引号
🧪 方法示例:
escape("订单号")拿到[订单号],原样escape("a,b")拿到["a,b"]- 字段里带引号时拿到
["说 ""Hi"""],内部引号翻倍 - 带换行的字段拿到
["第一行[LF]第二行"] escape(" 备注 ")拿到[" 备注 "],首尾空白被引号保住escape("张 三")拿到[张 三],中间空白不用加引号escape(null)拿到[],即空串- 数字与布尔分别拿到
42、3.14、true
四、工具类源码(可直接复制)
📦 源码文件