如何通过FlatPack在Java中读取无分隔符文本文件
嘿,刚好我用过FlatPack处理过这类固定宽度无分隔符的文本文件,给你一步步拆解怎么实现,完美匹配你要的类型转换需求!
用FlatPack解析固定宽度文本文件的完整步骤
1. 先引入FlatPack依赖
如果你的项目用Maven,直接在pom.xml里加这个依赖(用最新稳定版就行):
<dependency> <groupId>net.sf.flatpack</groupId> <artifactId>flatpack</artifactId> <version>3.4.0</version> </dependency>
Gradle项目对应调整依赖配置即可。
2. 编写字段映射XML文件(核心!)
FlatPack靠这个XML文件识别每个字段的位置、宽度和类型。首先你得先确定每个字段的固定宽度——根据你的示例数据,我梳理了大致的字段宽度(你可以根据实际文件微调):
- Prod Name: 8字符(比如
samsungA是7个字符,后面补1个空格) - City: 11字符(比如
London后面补5个空格,California后面补1个空格) - Price: 4字符(
6500、3500这类都是4位) - zipcode: 5字符(
14021这类5位) - Date: 10字符(
10/07/2018这种格式刚好10位)
然后创建一个product_mapping.xml文件,内容如下:
<?xml version="1.0"?> <!DOCTYPE PZMAP SYSTEM "http://flatpack.sourceforge.net/dtd/pzmap.dtd"> <PZMAP> <RECORD name="ProductData"> <!-- start从1开始计数,length是字段宽度,type指定转换类型 --> <COLUMN name="ProdName" start="1" length="8" type="STRING"/> <COLUMN name="City" start="9" length="11" type="STRING"/> <COLUMN name="Price" start="20" length="4" type="INTEGER"/> <COLUMN name="Zipcode" start="24" length="5" type="INTEGER"/> <COLUMN name="Date" start="29" length="10" type="DATE" format="dd/MM/yyyy"/> </RECORD> </PZMAP>
重点说明:
start:字段在每行的起始位置(从1开始计数)length:字段的固定字符数type:FlatPack支持自动转换的类型,比如STRING、INTEGER、DATE- 日期类型必须加
format,要和文件里的日期格式完全匹配
3. 编写Java解析代码
接下来写代码读取文件、解析并转换类型,直接上可运行的示例:
import net.sf.flatpack.DataSet; import net.sf.flatpack.DefaultParserFactory; import net.sf.flatpack.Parser; import net.sf.flatpack.ParserFactory; import java.io.FileReader; import java.text.SimpleDateFormat; import java.util.Date; public class FixedWidthFileReader { public static void main(String[] args) { try { // 1. 加载映射文件,创建固定宽度解析器 ParserFactory parserFactory = DefaultParserFactory.getInstance(); Parser parser = parserFactory.newFixedLengthParser(new FileReader("product_mapping.xml")); // 2. 指定要解析的文本文件 parser.setDataSource(new FileReader("your_data_file.txt")); // 3. 跳过第一行的表头(如果你的文件第一行是表头的话) parser.skip(1); // 4. 解析数据成DataSet DataSet dataSet = parser.parse(); // 5. 迭代每条数据,获取转换后的字段 while (dataSet.next()) { String prodName = dataSet.getString("ProdName").trim(); // 去掉可能的末尾空格 String city = dataSet.getString("City").trim(); int price = dataSet.getInt("Price"); int zipcode = dataSet.getInt("Zipcode"); Date date = dataSet.getDate("Date"); // 这里可以把数据存入实体类、数据库,或者直接打印验证 System.out.printf( "产品名: %s | 城市: %s | 价格: %d | 邮编: %d | 日期: %s%n", prodName, city, price, zipcode, new SimpleDateFormat("dd/MM/yyyy").format(date) ); } } catch (Exception e) { e.printStackTrace(); // 实际项目中建议用日志框架记录异常,方便排查 } } }
4. 关键注意事项
- 字段宽度一定要准确:这是固定宽度解析的核心,你可以用Notepad++这类编辑器打开文件,光标定位到字段首尾,数清楚字符数(包括填充的空格)。
- 处理多余空格:固定宽度文件通常会用空格填充字段,所以获取字符串字段后记得用
trim()去掉前后空格。 - 日期格式匹配:映射文件里的
format必须和文件中的日期格式完全一致,比如如果文件里是MM/dd/yyyy,就要改成对应的格式。 - 异常处理:实际项目中不要直接打印栈轨迹,最好用日志框架记录异常信息,方便后续排查问题。
内容的提问来源于stack exchange,提问作者Dazel Mann
相关产品推荐
相关产品推荐

