1. 简介

本文将带你快速掌握 Univocity Parsers —— 一个功能强大、性能优异的 Java 库,用于解析和生成 CSV、TSV 以及定长(fixed-width)格式的文本文件。

我们会从基础的文件读写操作讲起,逐步过渡到与 Java Bean 的绑定操作,最后介绍一些关键配置项。整个过程简洁高效,适合在实际项目中直接套用。

✅ 适合场景:大批量数据导入导出、ETL 工具开发、对接第三方系统文本接口等。
⚠️ 踩坑提示:别再用 OpenCSV 了,遇到复杂格式或性能要求高时,Univocity 真的是降维打击。

2. 项目依赖配置

要使用 Univocity Parsers,只需在 pom.xml 中引入以下 Maven 依赖:

<dependency>
    <groupId>com.univocity</groupId>
    <artifactId>univocity-parsers</artifactId>
    <version>2.8.4</version>
</dependency>

这个库不依赖其他第三方包,轻量且稳定,可以直接上生产。

3. 基础用法

3.1. 文件读取

✅ CSV/TSV 读取(极简模式)

直接通过 CsvParserTsvParser 将整个文件解析为 String[] 列表:

try (Reader inputReader = new InputStreamReader(
        new FileInputStream(new File("src/test/resources/productList.csv")), "UTF-8")) {
    
    CsvParser parser = new CsvParser(new CsvParserSettings());
    List<String[]> parsedRows = parser.parseAll(inputReader);
    return parsedRows;
} catch (IOException e) {
    // 异常处理
}

📌 想读 TSV?把 CsvParser 换成 TsvParser 即可,其他代码完全不变。

✅ 定长文件读取(fixed-width)

定长文件的关键是提前定义每列的宽度。你需要通过 FixedWidthFields 明确指定字段长度:

try (Reader inputReader = new InputStreamReader(
        new FileInputStream(new File("src/test/resources/productList.txt")), "UTF-8")) {
    
    FixedWidthFields fieldLengths = new FixedWidthFields(8, 30, 10);
    FixedWidthParserSettings settings = new FixedWidthParserSettings(fieldLengths);

    FixedWidthParser parser = new FixedWidthParser(settings);
    List<String[]> parsedRows = parser.parseAll(inputReader);
    return parsedRows;
} catch (IOException e) {
    // 异常处理
}

比如上面的例子表示三列:第一列 8 字符,第二列 30 字符,第三列 10 字符。


3.2. 文件写入

写操作和读操作对称,只需选择对应的 Writer 实现即可。

以下是一个通用方法,支持输出 CSV、TSV 和定长格式:

public boolean writeData(List<Object[]> products, OutputType outputType, String outputPath) {
    try (Writer outputWriter = new OutputStreamWriter(
            new FileOutputStream(new File(outputPath)), "UTF-8")) {
        
        switch(outputType) {
            case CSV:
                CsvWriter writer = new CsvWriter(outputWriter, new CsvWriterSettings());
                writer.writeRowsAndClose(products);
                break;
            case TSV:
                TsvWriter writer = new TsvWriter(outputWriter, new TsvWriterSettings());
                writer.writeRowsAndClose(products);
                break;
            case FIXED_WIDTH:
                FixedWidthFields fieldLengths = new FixedWidthFields(8, 30, 10);
                FixedWidthWriterSettings settings = new FixedWidthWriterSettings(fieldLengths);
                FixedWidthWriter writer = new FixedWidthWriter(outputWriter, settings);
                writer.writeRowsAndClose(products);
                break;
            default:
                logger.warn("无效的输出类型: " + outputType);
                return false;
        }
        return true;
    } catch (IOException e) {
        // 异常处理
    }
    return false;
}

📌 注意:定长写入必须提供字段宽度,否则会抛异常。


3.3. 使用行处理器(Row Processor)

当数据量较大时,你不希望一次性加载全部内容到内存。这时可以用 Row Processor 实现流式处理。

举个例子:使用 BatchedColumnProcessor 每次处理 5 行数据:

try (Reader inputReader = new InputStreamReader(
        new FileInputStream(new File(relativePath)), "UTF-8")) {
    
    CsvParserSettings settings = new CsvParserSettings();
    settings.setProcessor(new BatchedColumnProcessor(5) {
        @Override
        public void batchProcessed(int rowsInThisBatch) {
            // 每处理完一批就会触发
            System.out.println("已处理 " + rowsInThisBatch + " 行");
        }
    });
    
    CsvParser parser = new CsvParser(settings);
    parser.parse(inputReader); // 不再返回 List,而是由 processor 处理
} catch (IOException e) {
    // 异常处理
}

✅ 优势:内存友好,适合处理百万级数据。
⚠️ 注意:调用 parseAll() 会加载全部数据,而 parse() 配合 processor 才能实现流式处理。


3.4. 与 Java Bean 绑定读写

光处理字符串数组太原始了,实际开发中我们更希望直接映射到 POJO。

Univocity 支持通过注解自动绑定字段,简单粗暴。

✅ 定义带注解的 Bean

public class Product {

    @Parsed(field = "product_no")
    private String productNumber;
    
    @Parsed
    private String description;
    
    @Parsed(field = "unit_price")
    private float unitPrice;

    // getter 和 setter 省略
}

📌 关键注解是 @Parsed

  • 如果字段名和 CSV 列名一致,直接 @Parsed 即可;
  • 如果不一致,用 field 属性指定列名。

✅ 读取 CSV 到 Bean 列表

try (Reader inputReader = new InputStreamReader(
        new FileInputStream(new File("src/test/resources/productList.csv")), "UTF-8")) {
    
    BeanListProcessor<Product> rowProcessor = new BeanListProcessor<>(Product.class);
    CsvParserSettings settings = new CsvParserSettings();
    settings.setHeaderExtractionEnabled(true);  // 自动提取首行为 header
    settings.setProcessor(rowProcessor);
    
    CsvParser parser = new CsvParser(settings);
    parser.parse(inputReader);
    
    return rowProcessor.getBeans(); // 获取转换后的 Product 列表
} catch (IOException e) {
    // 异常处理
}

📌 核心是 BeanListProcessor,它会在解析过程中自动将每行数据映射为 Product 对象。


✅ 将 Bean 写入定长文件

try (Writer outputWriter = new OutputStreamWriter(
        new FileOutputStream(new File(outputPath)), "UTF-8")) {
    
    BeanWriterProcessor<Product> rowProcessor = new BeanWriterProcessor<>(Product.class);
    FixedWidthFields fieldLengths = new FixedWidthFields(8, 30, 10);
    FixedWidthWriterSettings settings = new FixedWidthWriterSettings(fieldLengths);
    
    settings.setHeaders("product_no", "description", "unit_price"); // 显式设置列头
    settings.setRowWriterProcessor(rowProcessor);
    
    FixedWidthWriter writer = new FixedWidthWriter(outputWriter, settings);
    writer.writeHeaders(); // 先写列头
    
    for (Product product : products) {
        writer.processRecord(product); // 逐条写入
    }
    writer.close();
    return true;
} catch (IOException e) {
    // 异常处理
}

📌 注意:

  • 必须设置 setRowWriterProcessor
  • processRecord() 是逐条写入的核心方法;
  • writeHeaders() 可选,但建议加上便于阅读。

4. 常用配置项(Settings)

Univocity 提供了丰富的配置选项,可以精细控制解析行为。

以下是一些常用配置示例:

CsvParserSettings settings = new CsvParserSettings();

// 限制单列最大字符数,防止 OOM
settings.setMaxCharsPerColumn(100);

// 限制最大列数,避免异常数据导致解析失败
settings.setMaxColumns(50);

// 启用自动检测列头(推荐开启)
settings.setHeaderExtractionEnabled(true);

// 设置跳过空行
settings.setEmptyValue(null);

// 设置引号、分隔符等(默认已适配大多数情况)
settings.getFormat().setDelimiter(';');
settings.getFormat().setQuote('"');

📌 小技巧:可以通过 settings.getFormat() 调整格式化细节,比如分隔符、换行符、引号等。

不同类型解析器的 settings 有共性也有差异:

  • CsvParserSettings / CsvWriterSettings
  • TsvParserSettings / TsvWriterSettings
  • FixedWidthParserSettings / FixedWidthWriterSettings

但整体使用模式高度统一,学一个等于会三个。


5. 总结

Univocity Parsers 是处理结构化文本文件的终极利器,具备以下优势:

✅ 支持 CSV、TSV、定长三种主流格式
✅ 性能强劲,远超 OpenCSV、Jackson CSV 等方案
✅ 提供 Java Bean 映射、流式处理、批量控制等高级功能
✅ API 设计清晰,配置灵活,文档齐全

📌 推荐使用场景:

  • 数据导入导出模块
  • 批量任务(如定时同步)
  • 接口对接(尤其银行、政府类系统常用定长格式)

最后,源码已托管在 GitHub:https://github.com/eugenp/tutorials/tree/master/libraries-data-2,建议集合备用。

🚀 下次遇到文本解析需求,别再手撸了,Univocity 直接安排上。


原始标题:Univocity Parsers