本文介绍如何读取固定格式的文本文件,根据指定位置的字段值(如第11-14位为"120")提取目标子串(如第47-67位),查询数据库获取对应新值,并原位替换——全程保持行结构不变,仅更新符合条件的记录。
本文介绍如何读取固定格式的文本文件,根据指定位置的字段值(如第11-14位为"120")提取目标子串(如第47-67位),查询数据库获取对应新值,并原位替换——全程保持行结构不变,仅更新符合条件的记录。
在处理银行、金融或EDI类固定宽格式(Fixed-width)文本文件时,常需基于业务规则对特定列进行条件化更新。本教程以一个典型场景为例:输入文件每行具有严格位置语义(如0–7位为序列号、11–14位为section编码、47–67位为待替换的OldValue),当且仅当section等于"120"时,需用数据库查得的NewValue替换该区间内容。
关键要点如下:
- ✅ 位置截取必须校验字符串长度,避免 StringIndexOutOfBoundsException;
- ✅ 数据库查询应复用连接与预编译语句(PreparedStatement),防止SQL注入并提升性能;
- ✅ 替换操作不可简单用 String.replace()(易误匹配),而应使用精确位置拼接确保只改目标区间;
- ✅ 输出需严格保留原行长度与空白布局(因下游系统依赖固定宽度)。
以下是完整可运行的Java实现(基于JDBC + HikariCP风格连接池思想,此处简化为单连接示例):
import java.io.*;
import java.sql.*;
public class FixedWidthReplacer {
private static final String DB_URL = "jdbc:h2:mem:testdb";
private static final String DB_USER = "sa";
private static final String DB_PASS = "";
public static void main(String[] args) {
String inputFile = "C:/Users/20230309.in";
String outputFile = "C:/Users/20230309.out";
try (Connection conn = DriverManager.getConnection(DB_URL, DB_USER, DB_PASS);
PreparedStatement stmt = conn.prepareStatement("SELECT NewValue FROM myTable WHERE OldValue = ?")) {
// 1. 读取所有行
File file = new File(inputFile);
BufferedReader reader = new BufferedReader(new FileReader(file));
String line;
StringBuilder outputContent = new StringBuilder();
while ((line = reader.readLine()) != null) {
// 2. 判断是否需处理:检查 section 是否为 "120"(位置11-14,含左闭右开)
if (line.length() >= 68 && "120".equals(line.substring(11, 14).trim())) {
String oldValue = line.substring(47, 67).trim(); // 提取 OldValue(去首尾空格便于查询)
// 3. 查询数据库
stmt.setString(1, oldValue);
ResultSet rs = stmt.executeQuery();
String newValue = oldValue; // 默认不替换
if (rs.next()) {
newValue = rs.getString("NewValue");
}
rs.close();
// 4. 精确位置替换:拼接 [0,47) + newValue(补足至20字符) + [67,end)
String paddedNewValue = String.format("%-20s", newValue); // 左对齐,不足20位补空格
line = line.substring(0, 47) + paddedNewValue + line.substring(67);
}
outputContent.append(line).append("\n");
}
reader.close();
// 5. 写出结果
try (BufferedWriter writer = new BufferedWriter(new FileWriter(outputFile))) {
writer.write(outputContent.toString());
}
System.out.println("处理完成,输出已保存至: " + outputFile);
} catch (Exception e) {
e.printStackTrace();
}
}
}⚠️ 注意事项:
- 空格敏感性:原始文件中OldValue字段(47–67)含大量尾部空格,substring(47,67) 取出的是20字符(含空格),但数据库查询时建议 .trim() 后匹配;写回时则需用 %-20s 格式化确保宽度一致。
- 性能优化:若文件行数极多(>10万)或DB查询频繁,应将 OldValue → NewValue 映射缓存为 Map<String, String>,避免重复查询。
- 事务与原子性:生产环境务必启用事务,并采用“先写临时文件,再原子替换原文件”策略,防止中断导致数据损坏。
- 编码安全:实际项目中严禁拼接SQL,本例已使用 PreparedStatement,切勿回退至字符串拼接。
通过上述方法,你既能精准控制字段级替换逻辑,又能无缝对接关系型数据库,满足金融级数据处理对准确性与可追溯性的严苛要求。

















