在制作小工具, 绿色软件时, 经常需要定义一些小型配置文件, 这些配置文件格式一般是针对具体业务的,是对业务的精准定义, 因此格式需要清爽简单。
需求描述
这里以一个端口转发的小工具的配置文件为例:
- 支持若干组端口转发配置同时工作
- 每组端口转发配置需要配置一个监听端口, 以及一组转发目标地址
- 每组转发目标地址包括一个ip和一个端口
用json描述如下[
{
"bind": 27011,
"forwarding":[
{"ip":"192.168.30.1", "port": 27011},
{"ip":"192.168.30.2", "port": 27011}
]
},
{
"bind": 27012,
"forwarding":[
{"ip":"192.168.30.1", "port": 27012},
{"ip":"192.168.30.2", "port": 27012}
]
},
{
"bind": 27013,
"forwarding":[
{"ip":"192.168.30.1", "port": 27013},
{"ip":"192.168.30.2", "port": 27013}
]
}
]
以上配置文件的意思是:
监听27011端口, 并将接收到的数据转发到192.168.30.1:27011上, 若该端口无法连接, 则发送到192.168.30.2:27011上.
接着的27012和27013端口也是同理。
直接使用json当配置文件当然是可以的, 而且有现成的类库解析,不过在这个场景下, 我更加倾向于使用自定义的格式, 这样看起来更加清爽, 比如以下格式:27011|192.168.30.1:27011|192.168.30.2:27011
27012|192.168.30.1:27012|192.168.30.2:27012
27013|192.168.30.1:27013|192.168.30.2:27013
我们需要把这段文本解析为List<Tuple<IPEndPoint, List<IPEndPoint>>>,
下面就描述如何自己编写代码来解析这段文本
硬编码解析
static List<Tuple<IPEndPoint, List<IPEndPoint>>> GetConfig() |
这段代码的思路是从配置文件读出所有行, 然后对每行以分隔符|进行切割,切割出各个字段后, 再一一分析, 填充进目标数据结构。
可以看到, 硬编码解析的话,代码比较冗长, 而且语义不清, 如果这段代码不是自己亲手写的, 甚至还难以看懂。
正则表达式解析
在解析思路不变的情况下, 我们可以用正则表达式改造以上代码:
static List<Tuple<IPEndPoint, List<IPEndPoint>>> GetConfig1() |
因为我们的示例比较简单, 使用正则表达式并未减少代码行数, 只不过使用正则表达式扩展性更强了
使用lambda表达式
为了压缩代码行数,以及更加清晰的语义表达, 我们还可以使用大杀器lambda表达式, 经过压缩后代码如下:
static List<Tuple<IPEndPoint, List<IPEndPoint>>> GetConfig2() |
可以看到代码行数下降了很多, 而且这种方式的表达更加清晰。完整代码