如何在 java 中使用 TelnetClient 解析 sqlci 查询的原始结果

how to parse raw result of sqlci query with TelnetClient in java

如何解析在 java 中使用 TelnetClient 执行的原始 sqlci 查询结果?

我正在尝试这样的事情:

        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";

        String[] headersAndValues = responeExample.split("\n\n");
        String[] headers = headersAndValues[0]
                .replaceAll("-", "")
                .replace("\n", "")
                .replaceAll(" +", " ")
                .trim()
                .split(" ");
        String values = headersAndValues[1];
        System.out.println("HEADERS: ["+headers.length+"]" + Arrays.toString(headers));
        System.out.println("VALUES: " + values);

有了这个我能够解析字符串数组中的响应头,但是响应值包含 spaces 并且一些值只是空白 space 就像最后一行值一样,如何我可以解析这个吗?

我使用拆分、修剪和替换解决了它,代码通过对具有不同值的不同表的多个查询对其进行了测试,并且所有这些都被正确解析。

映射器Class:

package utils;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class SqlciMapper {

    private final String rawResponse;
    private final List<Map<String, String>> resultList;
    private int results;
    private String[] headers;

    public SqlciMapper(String rawResponse) {
        this.rawResponse = rawResponse;
        this.resultList = new ArrayList<>();
        setResultsQuantity();
        map();
    }

    private void setResultsQuantity() {
        Pattern pattern = Pattern.compile("(?<=--- )(.*)(?= row)");
        Matcher matcher = pattern.matcher(this.rawResponse);
        if (matcher.find()) {
            this.results = Integer.parseInt(matcher.group(1));
        }else {
            this.results = -1;
        }
    }

    private String getRawHeaderRows() {
        String rawHeaders = rawResponse
                .replace("\r", "")
                .replace("\n\n--- (.*) row(.*)", "")
                .split("\n\n", 2)[0];

        setHeaders(rawHeaders);
        return rawHeaders;
    }

    private List<String> getRawResultRows() {
        List<String> rawResponses = new ArrayList<>();

        String rawResponsesStr = rawResponse
                .replace("\r", "")
                .replaceAll("\n\n--- (.*) row(.*)", "")
                .split("\n\n", 2)[1];

        int currentRow = 0;

        String[] rawResponsesArr = rawResponsesStr.split("\n");

        for (int i = 0; i < results; i++) {
            StringBuilder stringBuilder = new StringBuilder();
            int divisor = rawResponsesArr.length / results;
            for (int j = 0; j < divisor; j++) {
                stringBuilder.append(rawResponsesArr[j+currentRow]).append("\n");
            }
            rawResponses.add(stringBuilder.toString());
            currentRow+= divisor;
        }

        return rawResponses;
    }

    private void setHeaders(String rawHeaders) {
        this.headers = rawHeaders
                .replaceAll("-", "")
                .replace("\n", "")
                .replaceAll(" +", " ")
                .trim()
                .split(" ");
    }

    private List<String> getHeaderRows() {
        String rawHeaders = getRawHeaderRows();
        List<String> headerRows = new ArrayList<>(headers.length);
        for (String rawHeader : rawHeaders.replaceAll("-", "").split("\n")) {
            if (rawHeader.trim().equals("\n") || rawHeader.trim().isEmpty()) {
                continue;
            }

            headerRows.add(rawHeader);
        }

        return headerRows;
    }

    private void map() {
        List<String> rawResults = getRawResultRows();
        List<String> headerRows = getHeaderRows();

        rawResults.forEach(rawResult -> {
            List<String> valuesRows = Arrays.asList(rawResult.split("\n", headers.length));

            Map<String, String> resultMap = new HashMap<>();

            int currentIndex = 0;

            while (resultMap.size() != headers.length) {
                String currentHeadersRow = headerRows.get(currentIndex);
                String currentValuesRow = valuesRows.get(currentIndex);

                String[] headersSplit = currentHeadersRow.replaceAll(" +", " ").trim().split(" ");

                for (int i = 0; i < headersSplit.length; i++) {
                    if (i+1 == headersSplit.length) {
                        resultMap.put(headersSplit[i], rightTrim(currentValuesRow));
                        break;
                    }

                    String nextTarget = headersSplit[i+1];
                    int nextTargetIndex = currentHeadersRow.indexOf(nextTarget);

                    if (currentValuesRow.length() < nextTargetIndex) {
                        nextTargetIndex = currentValuesRow.length();
                    }

                    String currentTargetValue = currentValuesRow.substring(0, nextTargetIndex);
                    resultMap.put(headersSplit[i], rightTrim(currentTargetValue));
                    currentHeadersRow = currentHeadersRow.substring(nextTargetIndex);
                    currentValuesRow = currentValuesRow.substring(nextTargetIndex);
                }
                currentIndex++;
            }

            addResultRow(resultMap);

        });
    }

    private void addResultRow(Map<String, String> resultMap) {
        resultList.add(resultMap);
    }

    public List<Map<String, String>> get() {
        return resultList;
    }


    private String rightTrim(String s) {
        int i = s.length()-1;
        while (i > 0 && Character.isWhitespace(s.charAt(i))) {
            i--;
        }
        return s.substring(0,i+1);
    }

}

显然这不是最干净的解决方案,但它确实有效,它有几处需要改进但作为初始版本它很好。

使用示例:

public static void main(String[] args) {
        String rawResponse =
                "\n" +
                        "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" +
                        "PRE                               N                            .0000\n" +
                        "\n" +
                        "\n" +
                        "--- 1 row";

        List<Map<String, String>> results = new SqlciMapper(rawResponse).get();

        results.forEach(resultMap -> {
            System.out.println("----------");
            resultMap.forEach((k, v) -> System.out.println("["+k+"] ["+v+"]"));
        });
}

输出:

----------
[CLI_IND_SEX] [M]
[CLI_RTA] [                .0000]
[CLI_IND_PER_EMP] [P]
[CLI_COD_ECV] [SOL]
[CLI_NOM_FTS] [ ]
[CLI_IDC] [005752983]
[CLI_IND_CNV] [N]
[CLI_COD_EJE] [RFERNAS]
[CLI_APE_PTN] [NO TOCAR]
[CLI_NOM] [CELULA]
[CLI_APE_MTN] [TDM]
[CLI_COD_SOC_ECO] [ ]
[CLI_COD_EST] [VIG]
[CLI_COD_TIP_BCA] [PRE]
[CLI_PDO_STO] []
[CLI_COD_ACV] [95001]
[CLI_VRT] [0]
[CLI_COD_OFI] [090]
[CLI_COD_PLN] []
[CLI_CIC] [    98707514]
[CLI_FEC_NAC] [ 1990-01-01]
[CLI_TIP] [CL]
[CLI_COD_STO] []