与公司后端对接的时候erlang工程师经常丢过来这样一串字符串

{{1,7,[1,[2,3]]},3}"

或是这样一串

[{1,7,[1,[2,3]]},3]"

有点类似json又不是json,因为括号会出现多次也不适合用正则解析。这种情况怎么办呢?

解决方案如下:

1.观察规律:

每个括号是一对对存在 ’[‘对应‘]’,表示包含一个数组,‘{’对应'}',表示包含一个类,最前面的括号对应最后面的括号,考虑使用栈进行括号匹配

类或数组没有明确指明字段名,也可能出现 有字段名的(暂时无此需求,本文代码只针对无字段名形式的,后续有遇到会进行文章更新),定义一个erlangObject的类,可以往里面存数组或者类,若无指定字段则从1开始做为编号做属性名

2.代码实现:

先定义ErlangObject类,这里我使用了一个map保存属性,假设一个object是一个map,属性名是map的key,属性值就是key对应的值

import com.alibaba.fastjson.JSONException;
​
import java.util.HashMap;
import java.util.Map;
​
/*** erlang虚拟对象*/
public class ErlangObject {Map<String,Object> map ;
​public ErlangObject(){map = new HashMap<>();}
​public void putString(String key,String data){map.put(key,data);}
​public String getString(String key,String data){if (map.containsKey(key)){return map.get(key).toString();}else {return data;}
​}
​public void put(String key,Object data){map.put(key,data);}
​public Object get(String key){if (map.containsKey(key)){return map.get(key);}else {return null;}
​}
​@Overridepublic String toString() {return map.toString();}
}
复制代码

接下来是主要的转换类,这里使用单例加载。enClass就是解析类,enList就是解析数组。

两种思路差不多,enClass将{}里面的字符一个个遍历,遇到逗号则把遍历到的字符拼成字符串填入erlangObjet的一个属性(当出现括号{与[时,会将符号压入栈,表示这后面一段字符串是一个类或者数组的属性,在出现该括号对应的结束符之前会忽略逗号,出现对应逗号后,在解析这段数据写入erlangObjetobject)

enClass将[]里面的字符一个个遍历,遇到逗号则把遍历到的字符拼成字符串填入数组(当出现括号{与[时,会将符号压入栈,表示这后面一段字符串是一个类或者数组的属性,在出现该括号对应的结束符之前会忽略逗号,出现对应逗号后,再解析这段数据填入数组)

import java.util.*;
​
/*** erlang转换工具*/
public class ErlangManager {// pair以右括号为key, 左括号为值private Map<Character, Character> pair = null;
​private static ErlangManager erlangManager;
​private ErlangManager(){pair = new HashMap<Character, Character>();// pair.put(')', '(');pair.put('}', '{');pair.put(']', '[');}
​public static ErlangManager getInstance(){if (erlangManager==null){erlangManager = new ErlangManager();}return erlangManager;}
​
​/***  转为erlang类*  {}* @param s* @return* @throws ErlangParseException*/public ErlangObject enClass(String s) throws ErlangParseException{if (s==null) throw new ErlangParseException();s = s.replace("\n","").replace("\r","").replace(" ","");//不是 {}格式则抛出异常if (!s.startsWith("{")||!s.endsWith("}")) throw new ErlangParseException();//长度为2则是空内容if (s.length()==2) s = "";//否则去掉两边括号else s = s.substring(1,s.length()-1);//用临时栈存储括号Stack<Character> sc = new Stack<Character>();//定义一个erlangObject节点ErlangObject erlangObject = new ErlangObject();StringBuilder sb = new StringBuilder();int keyindex = 1;  //当前无返回属性名,从1开始做为编号做属性名for (int i = 0; i < s.length(); i++){Character ch = s.charAt(i);//遇到逗号如果栈是空的,就存为一个属性,否则当当前属性的内容if (ch==','&&sc.empty()){//递归存储erlang对象erlangObject.put(keyindex + "",getObject(sb.toString()));keyindex++;sb.delete( 0, sb.length() );continue;}sb.append(ch);if (pair.containsValue(ch))// 如果是左括号,放⼊栈中{sc.push(ch);} else if (pair.containsKey(ch)&&!sc.empty()&&sc.peek() == pair.get(ch)) // 如果匹配到对应的右括号就出栈{sc.pop();}//读取完字符串把最后一个数据放入虚拟erlang对象if (i == s.length()-1){erlangObject.put(keyindex + "",getObject(sb.toString()));}}return erlangObject;}
​/*** 转为object数组* []* @param s* @return* @throws ErlangParseException*/public List<Object> enList(String s) throws ErlangParseException{if (s==null) throw new ErlangParseException();s = s.replace("\n","").replace("\r","").replace(" ","");if (!s.startsWith("[")||!s.endsWith("]")) throw new ErlangParseException();if (s.length()==2) s = "";else s = s.substring(1,s.length()-1);Stack<Character> sc = new Stack<Character>();List<Object> erlangObjectList = new ArrayList<>();StringBuilder sb = new StringBuilder();for (int i = 0; i < s.length(); i++){Character ch = s.charAt(i);if (ch==','&&sc.empty()){
​erlangObjectList.add(getObject(sb.toString()));sb.delete( 0, sb.length() );continue;}sb.append(ch);if (pair.containsValue(ch))// 如果是左括号,放⼊栈中{sc.push(ch);} else if (pair.containsKey(ch)&&!sc.empty()&&sc.peek() == pair.get(ch)) // 如果是右括号{sc.pop();}if (i == s.length()-1){erlangObjectList.add(getObject(sb.toString()));}}return erlangObjectList;}
​
​/*** 通过字符串前缀获取object* @param str* @return*/private Object getObject(String str){try {if (str.startsWith("{")) {return enClass(str);} else if (str.startsWith("[")) {return enList(str);} else {return str;}}catch (Exception e){return str;}}
}
复制代码

还要为我们的转换定制一个异常

/*** Created by dengzhenli on 2019/1/5.* erlang定制异常*/
public class ErlangParseException extends RuntimeException {
​private static final long serialVersionUID = 1L;
​public ErlangParseException(){super();}
​public ErlangParseException(String message){super(message);}
​public ErlangParseException(String message, Throwable cause){super(message, cause);}
}
复制代码

测试一下

public class ErTest {
​public static void main(String[] args) {
//ErlangManager judger =  ErlangManager.getInstance();try {System.out.println(judger.enClass(null));System.out.println(judger.enClass("{{1,7,[1,[2,3]]},3}"));System.out.println(judger.enClass("{player_yaodan,11166672,885,[{yaodan,809,35,1,1600,[]},{yaodan,795,47,1,1600,[]},{yaodan,827,90,1,1600,[]},{yaodan,829,29,1,1600,[]},{yaodan,819,66,1,1600,[]},{yaodan,733,41,1,1600,[]},{yaodan,738,11,1,1600,[]},{yaodan,745,78,1,1600,[]},{yaodan,747,5,1,1600,[]},{yaodan,751,47,1,1600,[]},{yaodan,679,90,1,1600,[]},{yaodan,692,96,1,1600,[]},{yaodan,494,96,1,1600,[]}],[],[],400,[2,5,1],true}"));}catch (Exception e){e.printStackTrace();}
​}
​
​
}
复制代码

运行结果如下,可看到成功解析出了我们想要的格式

使用java进行erlang字符解析相关推荐

  1. Erlang转JAVA,将Erlang UTF-8编码的字符串转换为java.lang.String

    Java节点接收以UTF-8编码的Erlang字符串.它的类类型是OtpErlangString.如果我只是执行.toString()或.stringValue(),则生成的java.lang.Str ...

  2. Java IO: 其他字符流(下)

    转载自   Java IO: 其他字符流(下) 作者: Jakob Jenkov 译者: 李璟(jlee381344197@gmail.com) 本小节会简要概括Java IO中的PushbackRe ...

  3. java使用SAX接口解析xml文件

    全栈工程师开发手册 (作者:栾鹏) java教程全解 java使用SAX接口解析xml文件.实现解析类,从xml解析开始到结尾,每一步均会触发对象的重载函数. 测试代码,将book1.xml改成你自己 ...

  4. java.lang.IllegalArgumentException: 字符[_]在域名中永远无效。 at

    [http-nio-8080-exec-1] org.apache.coyote.AbstractProcessor.parseHost [xxx_tomcat] 是无效主机注意:更多的请求解析错误将 ...

  5. XML解析 (JAVA解析xml文件)java+Dom4j+Xpath xml文件解析根据子节点得到父节点 查找校验xml文件中相同的节点属性值 java遍历文件夹解析XML

    XML解析 (JAVA解析xml文件)java+Dom4j+Xpath xml文件解析根据子节点得到父节点 以及查找xml文件中相同的节点属性值 项目背景:这是本人实习中所碰到的项目,当时感觉很棘手, ...

  6. 细说Java中的字符和字符串(一)

    #一道经典问题 Java里的char类型能不能存储一个中文字符? 对于这道题,绝大多数的答案都是"可以存储".给出的原因包括: java中的char是unicode存储,unico ...

  7. 【Java 解析全国地址】Java 利用正则表达式完美解析全国省市区地址

    Java 利用正则表达式完美解析全国省市区地址 一.问题场景描述 最近在项目中遇到了一个全国地址解析的一个场景,前端会传来一个字符串,后端需自动解析出 xx省xx市xx区+详细地址 的这种格式. 因为 ...

  8. java实现Excel文件解析---apache POI以及把汉字转化为拼音

    java实现Excel文件解析----apache  POI以及把汉字转化为拼音 1.POI简介 Apache POI是Apache软件基金会的开放源码函式库,POI提供给Java程序对Microso ...

  9. Java基础2019最新Java面试经典题解析

    Java基础2019最新Java面试经典题解析 1简述JVM.JRE.JDK的区别 JVM:java虚拟机 ,加载.class并运行.class JRE:java运行环境除了包含JVM以外还包含了运行 ...

最新文章

  1. Java Sort中Comparator的语义分析
  2. Redis通信协议(protocol)
  3. NLP中对困惑度感到困惑?
  4. select/poll原理(阻塞挂起) 正常(阻塞轮询)
  5. SAP 电商云 Spartacus UI 支持延迟加载的新功能的入口设计
  6. ios uiwindow弹窗_iOS 你需要的弹窗大全
  7. 【渝粤教育】电大中专药事管理与法规 (2)作业 题库
  8. 小学有学计算机课程,如何进行小学计算机课程有效教学.doc
  9. 『TensorFlow』通过代码理解gan网络_中
  10. drupal_Drupal,物联网和开放式硬件的交集
  11. 马化腾:5G和AI双核驱动下,产业互联网的春天来了
  12. puppet进阶指南——cron资源详解
  13. 服务器位置设置,服务器部署位置
  14. 中国四大名著的文化价值
  15. Hive建外表操作以及其它修改表操作 hive外表与内表区别
  16. 岌岌可危 中立之争决定云计算未来
  17. 实验吧唯快不破writeup
  18. Java SE第10章 异常处理
  19. MS-DOC 文件格式概述
  20. Oracle如何保持一致读?

热门文章

  1. 在微信小程序的JS脚本中使用Promise来优化函数处理
  2. java MD5 加密
  3. mysqldiff对比主从表结构是否一致
  4. PythonGUI开发:59行代码开发小型商店添加系统
  5. 集中化监控SQL Server数据库
  6. 智能网联汽车到底该怎么玩?腾讯在成都放了个大招
  7. TTL电平、CMOS电平、RS232电平的区别
  8. RMAN快速入门指南
  9. 【Vista中系统准备工具存在隐患,自动清除用户资料】
  10. PXE自动化安装系统