Java中如何使用TelnetClient解析SQLCI查询的原始返回结果
Java解析SQLCI固定宽度返回结果的解决方案
你遇到的本质是固定宽度格式化表格的解析问题,这类表格不是用分隔符区分字段,而是靠固定列宽对齐,因此不能直接按空格拆分内容。正确的处理思路是先通过表头下方的-分隔线计算每一列的坐标区间,再按区间截取内容,即可完美处理值含空格、空值的场景。
实现步骤
- 从返回结果中分离表头区和数据区
- 提取表头中所有全是
-和空格的分隔线行,拼接为完整的分隔线总串 - 遍历分隔线总串,记录每一段连续
-的起止坐标,作为对应列的截取范围 - 拼接表头的所有文本行,按列范围截取得到表头字段数组
- 拼接单条数据的所有行,按列范围截取得到对应的值数组
完整实现代码
import java.util.ArrayList; import java.util.Arrays; import java.util.List; public class SqlciParser { public static void main(String[] args) { String responeExample = "CLI_IDC CLI_VRT CLI_IND_PER_EMP CLI_TIP CLI_CIC CLI_COD_EST\n" + "------------- ------- --------------- ------- ------------ -----------\n" + "CLI_APE_PTN CLI_APE_MTN CLI_NOM\n" + "------------------------- ------------------------- -------------------------\n" + "CLI_IND_SEX CLI_COD_ACV CLI_COD_EJE CLI_COD_ECV CLI_FEC_NAC\n" + "----------- ----------- ------------ ----------- -----------\n" + "CLI_NOM_FTS CLI_COD_OFI CLI_COD_PLN\n" + "---------------------------------------- ----------- -----------\n" + "CLI_COD_TIP_BCA CLI_COD_SOC_ECO CLI_IND_CNV CLI_RTA\n" + "--------------- --------------- ----------- ---------------------\n" + "CLI_COD_STO CLI_PDO_STO\n" + "----------- -----------\n" + "\n" + "005752983 0 P CL 98707514 VIG\n" + "NO TOCAR TDM CELULA\n" + "M 95001 RFERNAS SOL 1990-01-01\n" + " 090\n" + "PP N .0000\n" + "\n"; // 1. 分离表头和数据 String[] headersAndValues = responeExample.split("\n\n"); String[] headerLines = headersAndValues[0].split("\n"); String[] dataLines = headersAndValues[1].split("\n"); // 2. 拼接分隔线总串、表头文本总串 StringBuilder separatorSb = new StringBuilder(); StringBuilder headerTextSb = new StringBuilder(); for (String line : headerLines) { if (line.matches("^[- ]+$")) { // 匹配分隔线行 separatorSb.append(line); } else { headerTextSb.append(line); } } String separatorLine = separatorSb.toString(); String headerTextLine = headerTextSb.toString(); // 3. 计算每列的起止坐标 List<int[]> columnRanges = new ArrayList<>(); int start = -1; for (int i = 0; i < separatorLine.length(); i++) { if (separatorLine.charAt(i) == '-' && start == -1) { start = i; } else if (separatorLine.charAt(i) != '-' && start != -1) { columnRanges.add(new int[]{start, i}); start = -1; } } if (start != -1) { // 处理最后一列 columnRanges.add(new int[]{start, separatorLine.length()}); } // 4. 解析表头数组 String[] headers = new String[columnRanges.size()]; for (int i = 0; i < columnRanges.size(); i++) { int[] range = columnRanges.get(i); int endIdx = Math.min(range[1], headerTextLine.length()); headers[i] = headerTextLine.substring(range[0], endIdx).trim(); } // 5. 拼接数据行总串 StringBuilder dataSb = new StringBuilder(); for (String line : dataLines) { dataSb.append(line); } String dataLine = dataSb.toString(); // 6. 解析值数组 String[] values = new String[columnRanges.size()]; for (int i = 0; i < columnRanges.size(); i++) { int[] range = columnRanges.get(i); int endIdx = Math.min(range[1], dataLine.length()); if (range[0] >= dataLine.length()) { values[i] = ""; } else { values[i] = dataLine.substring(range[0], endIdx).trim(); } } // 输出结果验证 System.out.println("表头数量:" + headers.length); System.out.println("表头:" + Arrays.toString(headers)); System.out.println("值:" + Arrays.toString(values)); // 验证含空格的值和空值 System.out.println("CLI_APE_PTN的值:" + values[Arrays.asList(headers).indexOf("CLI_APE_PTN")]); System.out.println("CLI_NOM_FTS的值:" + values[Arrays.asList(headers).indexOf("CLI_NOM_FTS")]); } }
运行结果验证
- 可以正确解析到含空格的值
CLI_APE_PTN = NO TOCAR - 空值字段
CLI_NOM_FTS会返回空字符串,不会错位 - 所有字段和表头一一对应,不会出现长度不匹配的问题
多数据行扩展
如果返回结果包含多条数据,只需用\n\n拆分数据区,每个块单独按上述逻辑解析即可。
内容的提问来源于stack exchange,提问作者fneira
相关产品推荐
相关产品推荐

