Rdf-File根据协议布局模板和数据定义模板,来进行文件的解析与生成。通过协议布局和数据定义模板,能够明确计算出头尾占用的行数,这样可以更精确的分离出head,body,tail。
目前组件实现的协议布局模板可以分为如下两大类:
-
开放式基金业务数据交换协议 这种国家标准文件, 数据是以补位后定长形式展示的。 存在缺点有:
-
文件虽然是文本格式,但是内容肉眼无法看懂。
-
定长补位导致文件存储浪费。
-
因为是国家标准,文件内容定义十分全面,但是实际标准定义了六七十个字段, 有用的就十来个, 没用的字段也需要占用存储空间。
-
字段通过分隔符分割, 字段内容由交互双方约定。优点是用多少就占用多少,缺点是各方文件格式、内容差异可能比较大。
一:SP
SP是简单格式simple的意思。
sp协议布局模板
<protocol name="sp"><head><row><column><output>${column.value()}</output></column></row></head><body><row><column><output>${column.value()}</output></column></row></body><tail><row><column><output>${column.value()}</output></column></row></tail>
</protocol>
- 文件布局分为head, body, tail 三部分。
- head, body, tail字段都是横向输出,根据分隔符连接而成。
- head,tail 都只有一行。
sp 数据定义模板示例
{"head": ["totalCount|总笔数|Required|Integer","totalAmount|总金额|BigDecimal|Required"],"body": ["seq|流水号","instSeq|基金公司订单号|Required","gmtApply|订单申请时间|Date:yyyy-MM-dd HH:mm:ss","date|普通日期|Date:yyyyMMdd","dateTime|普通日期时间|Date:yyyyMMdd HH:mm:ss","applyNumber|普通数字|BigDecimal","amount|金额|BigDecimal","age|年龄|Integer","longN|长整型|Long","bol|布尔值|Boolean","memo|备注"],"tail": ["fileEnd|数据文件尾部字符|default:OFDCFEND"],"protocol": "SP"
}
SP文件示例
100|300.03
seq_0|inst_seq_0|2013-11-09 12:34:56|20131109|20131112 12:23:34|23.33|10.22|22|12345|true|备注1
seq_1|inst_seq_1|2013-11-10 15:56:12|20131110|20131113 12:33:34|23.34|11.88|33|56789|false|
OFDCFEND
二:DE
DE是余额宝与天弘交互格式,作为一种默认实现。
de协议布局模板
<protocol name="de"><head><row><column><output>${column.desc()}</output><output>:</output><output>${column.value()}</output></column></row><row output="${bodycolumn.horizontal(desc)}" /></head><body><row><column><output>${column.value()}</output></column></row></body><tail><row><column><output>${column.value()}</output></column></row></tail>
</protocol>
- 头部第一行由
字段描述:字段值
在由分隔符连接而成。 - 头部第二行由 组件函数
横向
打印出body的字段描述
。 - 没有文件尾, 协议可以定义尾部,只要数据定义模板不定义文件尾就行。
de数据定义模板示例
{"head":["totalCount|总笔数|Required|Long","totalAmount|总金额|BigDecimal|Required"],"body":["seq|流水号","instSeq|基金公司订单号|Required","gmtApply|订单申请时间|Date:yyyy-MM-dd HH:mm:ss","date|普通日期|Date:yyyyMMdd","dateTime|普通日期时间|Date:yyyyMMdd HH:mm:ss","applyNumber|普通数字|BigDecimal","amount|金额|BigDecimal","age|年龄|Integer","longN|长整型|Long","bol|布尔值|Boolean","memo|备注"],"protocol":"DE"
}
de文件示例
总笔数:2|总金额:300.03
流水号|基金公司订单号|订单申请时间|普通日期|普通日期时间|普通数字|金额|年龄|长整型|布尔值|备注
seq_0|inst_seq_0|2013-11-09 12:34:56|20131109|20131112 12:23:34|23.33|10.22|22|123|true|备注1
seq_1|inst_seq_1|2013-11-10 15:56:12|20131110|20131113 12:33:34|23.34|11.88|33|56789|false|
三:fund
国家标准:开放式基金业务数据交换协议
fund协议布局模板
<protocol name="fund" rowsplit="rowSplitByFixedlLength"><head><row columnLayout="vertical"><column><output>${column.value()}</output></column></row><row output="${bodycolumn.count()}" type="Integer|[3,0]" /><row output="${bodycolumn.vertical(name)}" /><row output="${totalCount}" type="Integer|[8,0]" /></head><body><row><column><output>${column.value()}</output></column></row></body><tail><row><column><output>${column.value()}</output></column></row></tail>
</protocol>
- fund协议文件数据是
定长
而不是通过分隔符分割的,不足的补0
。 - protocol标签的
name
用于指定协议名字,rowsplit
属性指定数据字段的分割方式。 - row标签的columnLayout定义了数据定义模板中的字段布局方式,这里是纵向布局,也就是一个字段一行 (默认是横向布局)。
bodycolumn.count()
是组件实现的内置列的数量。bodycolumn.vertical(name)}
输出列的字段名
。totalCount
组件内置变量,不用在数据定义模板中定义,数据行数
。- row的
type
属性定义变量的类型和长度。
fund数据定义模板示例
- OFDCFDAT:开始标志。
- OFDCFEND:结束标志。
{"head":["identity|信息标识|[8,0]|default:OFDCFDAT","version|协议版本号|[4,0]|default:20","msgCreator|信息创建人|[9,0]|default:H0","msgRecipient|信息接收人|[9,0]","sendDate|传送发生日期|[8,0]|Date:yyyyMMdd","summaryTableNo|汇总表号|[3,0]","fileTypeCode|文件类型代码 |[2,0]","sender|发送人|[8,0]|default:H0","recipient|接收人|[8,0]"],"body":["TransactionCfmDate|对帐日期|[8,0]|Date:yyyyMMdd","FundCode|基金代码|[8,0]","AvailableVol|基金可用份数|BigDecimal|[6,2]"],"tail":["fileEnd|数据文件尾部字符|default:OFDCFEND|[8,0]"],"protocol":"FUND"
}
fund文件示例
Map<String, Object> head = new HashMap<String, Object>();
head.put("msgRecipient", "xxx");
head.put("sendDate", "20231122");
head.put("summaryTableNo", "aa");
head.put("fileTypeCode", "bb");
head.put("recipient", "ll");
head.put("totalCount", 1);Map<String, Object> row = new HashMap<String, Object>();
row.put("TransactionCfmDate", "20231122");
row.put("FundCode", "中国1");
// Integer|[6,2] 总长度6位,小数点2位,输出"004211"
row.put("AvailableVol", 42.11);
OFDCFDAT
20
H0
xxx
20231122
aa
bb
H0
ll
003
TransactionCfmDate
FundCode
AvailableVol
00000001
20231122中国1 004211
OFDCFEND
四:FUND_INDEX
fund_index body数据不是定长数据。
<protocol name="fund_index" rowsplit="rowSplitByFixedlLength"><head><row columnLayout="vertical"><column><output>${column.value()}</output></column></row><row output="${totalCount}" type="Integer|[3,0]" /></head><body><!-- 只有一个字段,定义成vertical 是为了避免调用行分割器, 因为fund_index body数据不是定长数据 --><row columnLayout="vertical"><column><output>${column.value()}</output></column></row></body><tail><row><column><output>${column.value()}</output></column></row></tail>
</protocol>
fund_index数据定义模板示例
{"head": ["identity|信息标识|[8,0]|default:OFDCFIDX","version|协议版本号|[4,0]|default:20","msgCreator|信息创建人|[9,0]|default:H0","msgRecipient|信息接收人|[9,0]","sendDate|传送发生日期|[8,0]|Date:yyyyMMdd"],"body": ["path|基金文件路径"],"tail": ["fileEnd|数据文件尾部字符|default:OFDCFEND|[8,0]"],"protocol": "FUND_INDEX"
}
fund_index文件示例
OFDCFIDX
20
H0
xxx
20180302
003
aaa/xxx/ccc
bbb/xxx/ccc
ccc/xxx/ccc
OFDCFEND