什么是解析短信的最佳方法

时间:2014-03-10 07:40:04

标签: java android parsing

我正在开发一个用于将短信解析为字符串的应用程序,我希望将其存储在sqlite数据库中。

以下是短信的外观示例。 广播时间付款的样本。

Airtime payment made for UGX5,000 to KKL(0909xxxx).
Your Balance is UGX10,000.
Thank you for using KKL MobileMoney.

手机存款样本

You have received UGX100,000 from 09006700. Reason:J.
Your balance is UGX170,000.

移动货币发送示例

You have sent UGX10,000 to 08970000.
Reason:j.
Your balance is UGX120,000.
Thank you for using KKL MobileMoney.

我感兴趣的是:   - 发送/接收/支付的金额。 - 收到/发送/付款的号码。 - 原因 - 平衡。

到目前为止,我已尝试使用分割功能。

虽然它不一致。我正在使用字符串标记的数组索引,但是在某些字符串上我得到一个索引输出绑定异常,但它在某些字符串上有效。

这是我到目前为止的代码......但是工作不一致!

if (str.startsWith(RECEIVED))
            {
                // for mm deposit
                Log.e("msg", str);
                String delimeter="[ .]+";
                String[] tokens= str.split(delimeter);
                for (int i=0;i < tokens.length;i++)
                {
                    Log.e("Test",tokens[i]);    
                    }                       
                    String amount =tokens[3];
                    String reason =tokens[6].trim();            
                    String number=tokens[5];
                    String balance=tokens[11];              
                    Log.e("Amount",amount);
                    Log.e("reasons",reason);
                    Log.e("number",number);
                    Log.e("balance",balance);
                    String type="Deposit";
                    db.addrecord(amount, type, reason, number, balance);
                    db.close();
            }
            else if(str.startsWith(SEND))
            {   
                // for sent sms
                Log.e("msg", str);           
            String delimeter="[ .]+";
            String[] tokens= str.split(delimeter);
            for (int i=0;i < tokens.length;i++)
            {
                Log.e("Test",tokens[i]);    
                }                   
                String amount =tokens[3];
                String reason =tokens[6].trim();                
                String number=tokens[5];
                String balance=tokens[11];                          
                Log.e("Amount",amount);
                Log.e("reasons",reason);
                Log.e("number",number);
                Log.e("balance",balance);               
                String type="Payment";
                db.addrecord(amount, type, reason, number, balance);
                db.close();
            }

        else if(str.startsWith(AIRTIMEPAYMENT))
        {       // for airtime sms
            Log.e("msg", str);
            String delimeter="[ .]+";
            String[] tokens= str.split(delimeter);
            for (int i=0;i < tokens.length;i++)
            {
                Log.e("Test",tokens[i]);    
                }                       
                String amount =tokens[4];
                String reason =tokens[0]+ " "+ tokens[1];   
                String number=tokens[7];
                String balance=tokens[11];              
                Log.e("Amount",amount);
                Log.e("reasons",reason);
                Log.e("number",number);
                Log.e("balance",balance);
                String type="Air Time ";
                db.addrecord(amount, type, reason, number, balance);
                db.close();
        }

有关如何最好地处理解析的任何提示/建议?

我是java / android程序员初学者!

罗纳德

以下是我对

进行的编辑
private Map<String, String> parseSms(String s){
    Map<String, String> ret = new HashMap<String, String>();
    s = s.replace("\n", "");
    StringTokenizer t = new StringTokenizer(s, ".");
    while (t.hasMoreTokens()){
        String b = t.nextToken().trim();
        if (b.startsWith("You have sent") ||(b.startsWith("You have received"))){
            String type = getType(b);
            String parsed = parseAmount(b);
            String number = parseNumber(b);
            ret.put("amount", parsed);
            ret.put("number", number);
            ret.put("type", type);
        }else if(b.startsWith("Your")){//balance
            String parsed = parseAmount(b);
            ret.put("balance", parsed);
        }else if (b.startsWith("Reason")){

            ret.put("reason", b.toString());
        }
        else if( b.startsWith("Airtime"))
        {
              String type = getType(b);
              String parsed = parseAmount(b);
              String number = parseNumber(b);
              ret.put("amount", parsed);
              ret.put("number", number);
              ret.put("reason", "Air Time Payment");
              ret.put("type", type);
          }else if(b.startsWith("Your")){//balance
            String parsed = parseAmount(b);
            ret.put("balance", parsed);

        }


    }

    return ret;
}

它解决了这个问题。

2 个答案:

答案 0 :(得分:3)

解析此类文本的最佳方法是使用正则表达式(RegEx)。

所以..你在你的应用程序中定义了几个正则表达式...并检查字符串是否匹配...如果是......那么你找到它了!。

花一些时间学习正则表达式..它们在解析时非常用。您可以使用网站http://rubular.com/来验证/测试正则表达式。

用于使用正则表达式解析/匹配字符串的代码的一个示例:

Pattern p = Pattern.compile("^(\\d+)\\s(\\d+)\\s(.*)$");
Matcher m = p.matcher(strAlarm);
if (m.matches(){
    int notificationId = Integer.parseInt(m.group(1));
    long timeInMsec = Long.parseLong(m.group(2));
    String message = m.group(3);
    ....
}

上面的例子解析了这种字符串“323 432 123 zxchzxc any kjhzcx”

作为一个小帮助..让我们解析你的第二个例子。

Pattern p=Pattern.compile("^You\\s+have\\s+received\\s+(\\S+)\\sfrom\\s+(\\d+)\\.\\sReason:\\w\\.\\s*Your\\sbalance\\sis\\s(\\S+)");
Matcher m = p.matcher(smsTextHere);
if (m.matches(){
    //m.group(1) -- is string containing UGX100,000
    //m.group(1) -- is string containing 09006700
    //m.group(1) -- is string containing UGX170,000.
}

答案 1 :(得分:2)

这是解析更强大的解决方案。

用您的常量替换相关的字符串。在循环方面,使用Map比String []更安全。您也可以使用与regexp匹配。

private void test(){

    String sms = "You have sent UGX10,000 to 08970000.\n" +
            "Reason:j.\n" +
            "Your balance is UGX120,000.\n" +
            "Thank you for using KKL MobileMoney.";

    /*String rec = "You have received UGX100,000 from 09006700. Reason:J.\n" +
            "Your balance is UGX170,000.";
    String air = "Airtime payment made for UGX5,000 to KKL(0909xxxx).\n" +
            "Your Balance is UGX10,000.\n" +
            "Thank you for using KKL MobileMoney.";
    */
    Map<String, String> data = parseSms(sms);
    saveToDB(data);

}


private void saveToDB(Map<String, String> data){
    db.addrecord(data.get("amount"), data.get("type"), data.get("reason"), data.get("number"), data.get("balance"));
    db.close();
}

private Map<String, String> parseSms(String s){
    Map<String, String> ret = new HashMap<String, String>();
    s = s.replace("\n", "");
    StringTokenizer t = new StringTokenizer(s, ".");
    while (t.hasMoreTokens()){
        String b = t.nextToken().trim();
        if (b.startsWith("You have sent") ||  (b.startsWith("Airtime") || (b.startsWith("You have received")))){
            String type = getType(b);
            String parsed = parseAmount(b);
            String number = parseNumber(b);
            ret.put("amount", parsed);
            ret.put("number", number);
            ret.put("type", type);
        }else if(b.startsWith("Your")){//balance
            String parsed = parseAmount(b);
            ret.put("balance", parsed);
        }else if (b.startsWith("Reason")){
            ret.put("reason", b.toString());
        }
    }

    return ret;
}

private String getType(String s){
    if (s.startsWith("You have sent"))//Use your constants
        return "Payment";
    else if (s.startsWith("Airtime"))
        return "Air time";
    else if (s.startsWith("You have received"))
        return "Deposit";

    return "Unknown";
}


private String parseNumber(String s){
    String numberFragment = s.substring(s.lastIndexOf(' '), s.length());//extract number
    return numberFragment;
}

private String parseAmount(String s){
    char[] arr = s.toCharArray();
    StringBuffer sb = new StringBuffer();
    boolean parsingNumber = false;
    for (char c: arr){
        if (Character.isDigit(c))
            parsingNumber = true;
        if (Character.isLetter(c)  && c != ',' )
            parsingNumber = false;
        if (parsingNumber && c == ' ')//we have reached end of digit series
            break; //done
        if (parsingNumber)
            sb.append(c);
    }

    return sb.toString();
}