1. 程式人生 > >根據模板提取變數資訊

根據模板提取變數資訊

問題來源:
  最近公司要做簡訊中轉服務平臺,由於是第一次接觸這個業務,中間跳了不少坑,其中有一部分就是:上游通道需要配置資訊模板,介面中提供可變資訊即可;下游通道則是隻能提供完整資訊,無法提供可變資訊(吐槽一下:就是太LAN,不想弄而已),沒有辦法,只好由我們自己完成可變資訊的提取,然後將可變資訊以固定格式提交到上游通道,可變資訊後面統稱為變數資訊。
  經過努力,完成了一個測試類,可以根據完整資訊內容和模板來自動提取出內容中的變數資訊,並可以根據完整資訊的長度來自動將模板分割成兩條或更多,以及對應條數的變數資訊,話不多說,直接上程式碼:

package com.hyfd.service;

import java.util.ArrayList;
import java.util.List;

public class ArgsGet {
    // 滿足資訊分割條件的長度(這裡設定為滿100字元即進行分割)
    private static final int STR_SPLIT_MAX_LENGTH = 100;
    public static void main(String[] args) {
        String smsStr = ToDBC("成吉思汗的騎兵,***速度與二十世紀的裝甲部隊相當;北宋的床弩,射程達"
                + "一千五百米,與二十世紀的狙擊×××差不多;但這些仍不過是古代的騎兵與×××而已,不可能與"
                + "現代力量抗衡。基礎理論決定一切,未來史學派清楚地看到了這一點。而你們,卻被迴光返照的"
                + "低階技術矇住了眼睛。你們躺在現代文明的溫床中安於享樂,對即將到來的決定人類命運的終極"
                + "決戰完全沒有精神上的準備。");
        getArgsList(smsStr);
    }

    /**
     * <h5>功能:獲取資訊拆分後的變數資訊</h5>
     * @param smsStr 完整資訊內容
     */
    private static List<String> getArgsList(String smsStr) {
        String ptTemplateAll = "#*#的騎兵,***速度與#*#世紀的裝甲部隊相當;#*#的#*#,射程達#*#米,"
                + "與#*#世紀的#*#差不多;但這些仍不過是古代的#*#與#*#而已,不可能與#*#力量抗衡。#*#決"
                + "定一切,#*#清楚地看到了這一點。而你們,卻被迴光返照的#*#矇住了眼睛。你們躺在#*#的溫床"
                + "中安於#*#,對即將到來的決定人類命運的#*#完全沒有精神上的準備。";
        String[] ptTemplate = ptTemplateAll.split("#\\*#");

        System.out.println("完整資訊[" + smsStr + "]");
        System.err.println("完整模板[" + ptTemplateAll + "]");

        // 拆分資訊內容
        List<String> smsList = smsSplit(smsStr, ptTemplate);
        // 根據資訊內容拆分模板
        List<List<String>> templateSplit = templateSplist(smsList, ptTemplate);
        for (int i = 0; i < templateSplit.size(); i++) {
            System.out.println("第" + (i + 1) + "段拆分模板" + templateSplit.get(i) + "");
        }

        List<String> argsList = new ArrayList<String>();
        // 根據拆分後的資訊內容和模板獲取對應的變數資訊
        for (int i = 0; i < smsList.size(); i++) {
            String tempSmsStr = smsList.get(i);
            List<String> templateSplist = templateSplit.get(i);
            for (String template : templateSplist) {
                if (!"".equals(template)) {
                    tempSmsStr = tempSmsStr.replaceFirst(template, ",");
                }
            }
            if (tempSmsStr.endsWith(",")) {
                tempSmsStr = tempSmsStr.substring(0, tempSmsStr.length() - 1);
            }
            argsList.add(tempSmsStr);
            System.err.println("第" + (i + 1) + "段變數資訊[" + tempSmsStr + "]");
        }
        return argsList;
    }

    /**
     * <h5>功能:拆分資訊內容</h5>
     * @param smsStr 完整資訊內容
     * @param ptTemplate 陣列化的模板資訊
     * @return 
     */
    private static List<String> smsSplit(String smsStr, String[] ptTemplate){
        List<String> smsList  = new ArrayList<String>();
        StringBuffer sbf = new StringBuffer();
        for (String template: ptTemplate) {
            if (!"".equals(template)) {
                // 一旦資訊內容長度超過100,則進行資訊拆分
                if (sbf.length() > STR_SPLIT_MAX_LENGTH) {
//                  System.out.println(sbf.toString());
                    smsList.add(sbf.toString());
                    sbf.setLength(0);
                }
                sbf.append(smsStr.substring(0, smsStr.indexOf(template) + template.length()));
                smsStr = smsStr.substring(smsStr.indexOf(template)+template.length());
            }
        }
        smsList.add(sbf.toString());
        return smsList;
    }

    /**
     * <h5>功能:根據資訊內容拆分模板</h5>
     * @param smsList 拆分後的資訊內容
     * @param ptTemplate 模板資訊
     * @return 
     */
    private static List<List<String>> templateSplist(List<String> smsList, String[] ptTemplate){
        List<List<String>> templateList  = new ArrayList<List<String>>();
        for (String smsStr : smsList) {
//          System.out.println(smsStr);
            // 1.獲取資訊結束標識
            String sbf = "";
            for (String template : ptTemplate) {
                if (!"".equals(template)) {
                    if (smsStr.endsWith(template)) {
//                      System.out.println(template+"="+smsStr.indexOf(template));
                        sbf = template;
                    }
                }
            }

            // 2.根據資訊標識,將資訊模板進行對應的拆分
            List<String> tempList = new ArrayList<String>();
            StringBuffer tempSbf = new StringBuffer();
            for (int i = 0; i < ptTemplate.length; i++) {
                tempSbf.append(ptTemplate[i]);
                if (!"".equals(tempSbf.toString())) {
                    tempList.add(tempSbf.toString());
                    if (sbf.equals(tempSbf.toString())) {
                        ptTemplate[i] = "";
                        break;
                    } else {
                        ptTemplate[i] = "";
                    }
                }
                tempSbf.setLength(0);
            }
            templateList.add(tempList);
//          System.out.println(JSONObject.toJSONString(tempList));
//          System.out.println("-----------------------------");
        }
        return templateList;
    }

    /**
     * <h5>功能:全形轉半形</h5>
     *  這個主要是為了規範資訊內容,因此對全形資訊做了半形處理,不用的時候從引用的地方直接去掉即可
     * @author zhangpj  @date 2018年11月5日
     * @param str
     * @return 
     */
    public static String ToDBC(String str) {
        char[] c = str.toCharArray();
        for (int i = 0; i < c.length; i++) {
            // 全形空格為12288,半形空格為32
            if (c[i] == 12288) {
                c[i] = (char) 32;
                continue;
            }
            // 其他字元半形(33-126)與全形(65281-65374)的對應關係是:均相差65248
            if (c[i] > 65280 && c[i] < 65375)
                c[i] = (char) (c[i] - 65248);
        }
        return new String(c);
    }
}

測試結果,可以看到模板分段並完美的獲取到了對應的變數資訊,效果如下

根據模板提取變數資訊

後記
  由於趕時間沒有做優化,如果有不當之處,歡迎各位大神指教,謝謝!