惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

L
LINUX DO - 热门话题
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
S
Security @ Cisco Blogs
W
WeLiveSecurity
N
News and Events Feed by Topic
Security Archives - TechRepublic
Security Archives - TechRepublic
V2EX - 技术
V2EX - 技术
TaoSecurity Blog
TaoSecurity Blog
L
LINUX DO - 最新话题
Cloudbric
Cloudbric
S
Secure Thoughts
Recent Commits to openclaw:main
Recent Commits to openclaw:main
C
CXSECURITY Database RSS Feed - CXSecurity.com
Forbes - Security
Forbes - Security
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
T
The Blog of Author Tim Ferriss
博客园 - 【当耐特】
NISL@THU
NISL@THU
F
Full Disclosure
博客园_首页
Blog — PlanetScale
Blog — PlanetScale
腾讯CDC
B
Blog
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
B
Blog RSS Feed
Jina AI
Jina AI
N
News | PayPal Newsroom
G
Google Developers Blog
P
Proofpoint News Feed
雷峰网
雷峰网
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
P
Proofpoint News Feed
PCI Perspectives
PCI Perspectives
H
Heimdal Security Blog
GbyAI
GbyAI
Project Zero
Project Zero
Hacker News - Newest:
Hacker News - Newest: "LLM"
Y
Y Combinator Blog
S
Schneier on Security
Hacker News: Ask HN
Hacker News: Ask HN
S
Security Affairs
P
Privacy & Cybersecurity Law Blog
Attack and Defense Labs
Attack and Defense Labs
美团技术团队
T
Threat Research - Cisco Blogs
T
Threatpost
The Hacker News
The Hacker News
C
Cisco Blogs
Last Week in AI
Last Week in AI
Google DeepMind News
Google DeepMind News

I'm OWenT

国产大模型(GLM 5.1、Kimi K2.6)真实场景效果和 Coding Plan 额度测试 新版本libatapp的连接管理——从etcd服务发现到拓扑驱动的自动重连 新版本libatbus的设计变更——从树形路由到拓扑驱动 Protobuf又一坑 - C++标准和ABI兼容性 AI真好用-给Blog主题统一加mermaid,chart.js,excalidraw,draw.io的多种引入方式支持 给内网部署Squid-通用HTTP下载缓存 UE使用CodeChecker和clang-tidy生成静态分析报告 找出UE的循环依赖 C++小协程栈和临时变量及作用域的栈溢出问题分析 游戏服务的可观测性能力建设(C++生态) 指标上报的多线程优化和多拉取源点优化 协程(libcopp)的Channel功能和CPU命中率优化 通用RPC代码生成器 实现strong_rc_ptr(比shared_ptr更快的引用计数智能指针) 手夯一个STL allocator和对象内存分析组件 std::condition_variable 的信号丢失问题 踩坑一处(GCC)STL std::async 实现BUG导致的crash问题 GCC 14的一个warning to error BUG 给xresloader(Excel导表工具)增强UE读表支持(包含蓝图,Blueprint) Opentelemetry社区在gRPC的几个链接问题(静态库和动态库混用,musl工具链,符号裁剪) Excel转表工具(xresloader)的新验证器(验证外部Excel和文本数据,唯一性和自定义规则) protobuf v22和gRPC v1.55版本升级的依赖变化和upb适配 关于protobuf近期版本(v20/v3.20+)和 gRPC v1.54版本在某些编译环境下的一些链接和编译问题 打通游戏服务端框架的C++20协程改造的最后一环 Opentelemetry-cpp的Logs模块标准更新(涉及近期版本:1.8-1.9的BREAK CHANGES) 给cmake-toolset和工具链(curl等)加HTTP/2和HTTP/3支持 又开新坑之 coredns 插件: nftables和filter 关于opentelemetry-cpp社区对于C++ Head Only组件单例和符号可见性的讨论小记 填个转表工具 xresloader 去年的坑(数组尾部裁剪) 集成 upb 和 lua binding 的踩坑小记 libcopp对C++20协程的接入和接口设计 再度优化GCC、LLVM、Clang、libc++、libc++abi等套件的构建脚本 游戏服务的分布式事务优化(二)- 事务管理 游戏服务的分布式事务优化(一)- Write Ahead Log(WAL) 模块 记录一些bazel适配用编译选项 测试现代化硬件C++浮点数性能和一致性 适配Boringssl和OpenSSL 3.0 近期cmake-toolset的一些适配问题 C++20 Text Formatting/fmtlib 适配问题小记 再次重构LLVM+Clang+libcxx+libc++abi+其他相关工具的构建流程 重构基于CMake的构建工具链 新版GCC和LLVM+Clang终于Release啦 折腾一下nftables下的双拨 [C++20] Module partitions和符号交叉引用(声明和实现分离) [Rust] 实现一个线程安全且迭代器可以保存的链表 基于protobuf的代码生成 几个使用protobuf中C++接口的Arena的坑 Amazon Aurora DB存储引擎论文阅读小记 近期对libatapp的一些优化调整(增加服务发现和连接管理,支持yaml等) xresloader转表工具链增加了一些新功能(map,oneof支持,输出矩阵,基于模板引擎的加载代码生成等) 在游戏服务器中使用分布式事务 libcopp接入C++20 Coroutine和一些过渡期的设计 libatbus 的大幅优化 nftables初体验 容器配置开发环境小计 PALM Tree - 适合多核并发架构的B+树 - 论文阅读小记 跨平台协程库 - libcopp 简介 C++20 Coroutine 性能测试 (附带和libcopp/libco/libgo/goroutine/linux ucontext对比) 尝鲜Github Action 一些xresloader(转表工具)的改进 protobuf、flatbuffer、msgpack 针对小数据包的简单对比 协程框架(libcopp) 小幅优化 Excel转表工具(xresloader) 增加protobuf插件功能和集成 UnrealEngine 支持 Anna(支持任意扩展和超高性能的KV数据库系统)阅读笔记 C++20 Coroutine libcopp merge boost.context 1.69.0 Google去中心化分布式系统论文三件套(Percolator、Spanner、F1)读后感 Rust玩具-企业微信机器人通用服务 使用ELK辅助监控开发测试环境服务质量和问题定位 2018年的新通用伪随机数算法(xoshiro / xoroshiro)的C++(head only)实现 Webpack+vue+boostrap+ejs构建Web版GM工具 Rust的第二次接触-写个小服务器程序 理解和适配AEAD加密套件 atsf4g-co的进化:协程框架v2、对象路由系统和一些其他细节优化 协程框架(libcopp)v2优化、自适应栈池和同类库的Benchmark对比 可执行文件压缩 初识Rust 使用restructedtext编写xresloader文档 atframework的etcd模块化重构 C++的backtrace ECDH椭圆双曲线(比DH快10倍的密钥交换)算法简介和封装 protobuf-net的动态Message实现 pbc的proto3接入 atgateway内置协议流程优化-加密、算法协商和ECDH 整理一波软件源镜像同步工具+DevOps工具 Blog切换到Hugo libcopp v2的第一波优化完成 libcopp(v2) vs goroutine性能测试 libcopp的线程安全、栈池和merge boost.context 1.64.0 GCC 7和LLVM+Clang+libc++abi 4.0的构建脚本 libatbus的几个藏得很深的bug 用cmake交叉编译到iOS和Android 开源项目得一些小维护 atapp的c binding和c#适配 对象路由系统设计 2016年总结 近期的一个协程流程BUG 重写了llvm+clang+libc++和libc++abi的构建脚本 atsf4g完整游戏工程示例|I'm OWenT atframework基本框架已经完成|I'm OWenT
xresloader-Excel导表工具链的近期变更汇总
owent · 2023-04-19 · via I'm OWenT

blog-website

前言

xresloader 是一组用于把Excel数据结构化并导出为程序可读的数据文件的导表工具集。它包含了一系列跨平台的工具、协议描述和数据读取代码。

主要功能特点:

  • 跨平台(java 11 or upper)
  • Excel => protobuf/msgpack/lua/javascript/json/xml
  • 完整支持协议结构,包括嵌套结构和数组嵌套
  • 同时支持protobuf proto v2 和 proto v3
  • 支持导出proto枚举值到lua/javascript代码和json/xml数据
  • 支持导出proto描述信息值到lua/javascript代码和json/xml数据(支持自定义插件,方便用户根据proto描述自定义反射功能)
  • 支持导出 UnrealEngine 支持的json或csv格式,支持自动生成和导出 UnrealEngine 的 DataTable 加载代码
  • 支持别名表,用于给数据内容使用一个易读的名字
  • 支持验证器,可以在数据里直接填写proto字段名或枚举名,或者验证填入数据的是否有效
  • 支持通过protobuf协议插件控制部分输出
  • 支持自动合表,把多个Excel数据表合并成一个输出文件
  • 支持公式
  • 支持oneof,支持plain模式输入字符串转为数组或复杂结构,支持map
  • 支持空数据压缩(裁剪)或保留定长数组
  • 支持基于正则表达式分词的字段名映射转换规则
  • 支持设置数据版本号
  • Lua输出支持全局导出或导出为 require 模块或导出为 module 模块。
  • Javascript输出支持全局导出或导出为 nodejs 模块或导出为 AMD 模块。
  • 提供CLI批量转换工具(支持python 2.7/python 3 @ Windows、macOS、Linux)
  • 提供GUI批量转换工具(支持Windows、macOS、Linux)
  • CLI/GUI批量转换工具支持include来实现配置复用

xresloader 包含了多个组件,其中最主要的部分分别是。

这个工具集已经开发了很长时间了,近两年陆陆续续也收到一些Feature Request,我抽空实现了一些,同时也收到了一些PR来增强功能。

近期主要变更和优化

xresloader-转表模块引擎的杂项优化和变更

对于 xresloader-转表模块引擎。首先有一些细碎的小变化:

  • 因为java 8已经逐渐时区主流支持,我们把对JRE的要求上升到了java 11。
  • 优化了文本类型的输出字段顺序,保证有序,这样便于版本迭代时使用diff工具查看变化。
  • Plain模式 的message数组允许指定下标。
  • 优化公式存在不支持函数时的输出,我们发现POI库对公式的支持有限。之前的输出会误导用户。
  • 增加了 -r/--descriptor-print 选项,用于导出所有描述数据,特别是导出整体描述数据到lua/javascript等脚本。
  • 抽离协议为单独的子模块,这样方便被更多的工具共享。
  • 修复Lua输出 </ 时追加了冗余的 \ 导致转移错误的问题。
  • 增加 --enable-string-macro 用于让Macro(文本替换),对字符串类型生效。或使用 --disable-string-macro 让Macro(文本替换),对字符串类型不生效。

启用内置的索引器

另外早先时候,有项目组反馈说使用 xresloader 转出一个超级大表(大约70万行数据)的时候耗时很长,并且会OOM。当时排查的原因是POI自带的索引开销太高了。 所以当时我基于POI库的流式接口自己实现了一个索引,CPU占用大约是POI的1/6,内存开销也低了一个数量级。

这个索引器一直处于试用阶段,经过比较长的时间测试之后,现在也是把默认的索引器切到这个内置索引了。这个内置索引和之前的相比牺牲了两个功能,一个是公式的实时重算。 因为Excel在保存时会根据当前的数据状态计算公式结果并保存在Cache里,所以即便没有公式重算,公式功能也是受支持的,这个实时重算意义也不是特别大。 另一个牺牲就是现在对日期时间类型的判定可能没有原先那么精准了,Excel预制的时间格式比较多,我没有全部去核查匹配。当然基本的格式还是可以检测到的。

由于新的索引器不支持公式重算,所以我服用了一个原来就有的选项: --enable-excel-formular ,用于告知 xresloader 使用老的索引器。这样对一些存量业务不方便修改或者有兼容性问题的还是可以切回到老版本。

重构UE输出的结构和对数组增加strip功能

如果一个Excel单元格没有填写内容,但是设置了格式,这时候接口读出来可能是有数据但是内容为空。 所以 xresloader 有一个功能是裁减掉Excel尾部的空数据。同时为了允许类似在Excel话地图、阵型的场景,提供了 --disable-empty-list 来关闭裁剪,强行填充空元素。

那么就有项目组提过一个Feature Request,希望可以不仅仅是裁剪 repeated 字段掉尾部的空数据,也可以裁剪掉头部的空数据或中间的空数据。于是我新加了一组选项 --list-keep-empty , --list-strip-all-empty--list-strip-empty-tail 来支持对裁剪的控制。

但是这里实现的时候出现一个比较麻烦的地方。因为UE对数据格式的输出有一些要求,之前UE的输出都是单独写的数据结构的映射。 特别是对UE-Csv格式的输出,我们采用流式的输出方式。在原先只裁剪尾部的时候,我们的实现可以是碰到数据以后填充前面缺失项目来补空数据。 而现在我们对单元格碰到空数据,是不能确定我们能不能补空项目的,因为要根据配置和后面是否有数据来判断。 当然我们也可以单独写数据裁剪的规则,根据配置和当前数组元素的位置来决定是走延后的填补,还是直接跳过空数据。 但是这就有4中输出的模式需要实现为一样的功能,再加上一些插件的行为处理,导致整体逻辑非常复杂。所以我就干脆彻底重构了这一块,让UE的数据先预处理到和之前Lua、Javascipt等文本输出一样的中间结构,再导出到UE DataTable所要求的数据格式中。

flowchart TD A[fa:fa-file-excel-o Excel文件] –> |数据源描述信息| H(数据源和索引器) H –> |protobuf描述/插件| B(数据验证器和插件预处理) B –> G(内置数据结构) G –> C{UE输出模块} C –> D[fa:fa-file UE-Json格式输出] C –> E[fa:fa-file-text UE-Csv格式输出] C –> F[fa:fa-code UE加载代码] C –> I[fa:fa-code UnreaImportSettings.json]

这样也能方便后续的新功能维护。

UE输出加载代码的定制化

我们之前集成测试的时候,UE还没有限制DataTable的Loader初始化( FObjectFinder )必须在构造函数中。后来有小伙伴提了个BUG,说(至少某些版本)UE如果Loader的初始化不在构造函数中会报错。 正好之前一直也在想加一些自定义Loader的功能,就顺便一起加上了。除了把默认Loader挪到构造函数之外,还增加了一些选项和插件,用于控制关闭默认行为。

  • 增加了 UeCfg-EnableDefaultLoader 这个选项,用于控制输出的代码默认情况下是否生成的Loader代码。
  • 增加了 org.xresloader.ue.default_loader=EN_LOADER_MODE_DEFAULT|EN_LOADER_MODE_ENABLE|EN_LOADER_MODE_DISABLE 插件,用来针对特定的数据特殊处理这个选项。
  • 增加了 UeCfg-IncludeHeader 选项,对所有输出的UE代码额外包含头文件,允许输出的代码增加包含头文件。
  • 增加了 org.xresloader.ue.include_header 插件用于对于特定的Message额外附加包含文件。

增加了Javascript的数据Patch机制

这里特别要感谢 @superwenda ,提供了通过Javascript二次处理数据的插件机制。并且增加了压力测试。

现在可以通过 CallbackScript=javascript脚本路径 的方式对中间数据做二次处理,在整个执行流程中内置数据和输出的中间插入了脚本支持。

flowchart TD A[fa:fa-file-excel-o Excel文件] –> |数据源描述信息| H(数据源和索引器) H –> |protobuf描述/插件| B(数据验证器和插件预处理) B –> G(内置数据结构) G –> |Javascript脚本处理数据| D(内置数据结构) D –> C{UE输出模块}

脚本会在初始化阶段执行 initDataSource() 接口,在每个数据行会执行 currentMessageCallback() 接口。并且会注入 gOurInstancegSchemeConf 用来在脚本里获取配置和描述信息。 具体的示例可以参考 https://github.com/xresloader/xresloader/blob/main/sample/cb_script.js

批量转表工具增加 tag/class 限定

现在允许针对某些装表条目设置为仅仅执行某些输出了,比如:

<?xml version="1.0" encoding="UTF-8"?>
<!-- <?xml-stylesheet type="text/xsl" href="helper/view.xsl"?> -->
<root>
    <global>
        <proto desc="协议类型,-p选项">protobuf</proto>
        <output_type desc="输出类型,-t选项,支持多个同时配置多种输出">bin</output_type>
        <output_type desc="可以通过指定class来限制输出的规则" rename="/(?i)\.bin$/\.csv/" class="client" >ue-csv</output_type>
        <!-- 其他无关设置不再列举 -->
    </global>
    <list>
        <item file="资源转换示例.xlsx" scheme="scheme_kind" name="人物表" cat="kind" class="server"></item>
        <item name="嵌套数组测试" cat="test" class="client server">
            <scheme name="DataSource" desc="数据源(文件名|表名|数据起始行号,数据起始列号)">资源转换示例.xlsx|arr_in_arr|3,1</scheme>
            <scheme name="ProtoName" desc="协议名">arr_in_arr_cfg</scheme>
            <scheme name="OutputFile" desc="输出文件名">arr_in_arr_cfg.bin</scheme>
        </item>
    </list>
</root>

这种情况中,嵌套数组测试 既会转出为protobuf二进制,又会转出为 。而 人物表 只会转出protobuf二进制。这样可以避免掉客户端或者服务器不需要关心的数据导出。

批量转表GUI工具增加事件的控制和自定义按钮

为了方便分程序同学使用,我们还提供了GUI工具。界面如下:

2304-01.gif

然后为了方便工具集成,我们给转变开始前和完成后都加入了事件机制,可以通过nodejs代码去控制后续行为去做一些工具集成。比如转表成功以后制动执行UE-Command的Import去把数据导入到DataTable中。 但是后来有其他项目组同学提出希望可以控制跳过某些事件。因为有些流程可能本地调试用,全跑完事件流程会比较慢,同时希望可以提供功能来按规则一键选中某些需要转的表的条目。 所以一方面我给命名事件(有 name 字段)增加了可选的开关。同时为了方便进一步支持扩展行为,增加了一组自定按钮的配置,可以配置为按通配符或者正则表达式选中和反选转表条目。 甚至允许执行配置在xml里的脚本。比如以下自定义按钮的配置:

[{
    "name": "自定义按钮-按Scheme",
    "by_schemes": [{
        "file": "资源转换示例.xlsx",
        "scheme": "glob: *"
    }],
    "default_selected": false
}, {
    "name": "自定义按钮-按Sheet",
    "by_sheets": [{
        "file": "资源转换示例.xlsx",
        "sheet": "regex: .*"
    }],
    "default_selected": true,
    "style": "outline-primary"
}, {
    "name": "刷新自定义按钮",
    "action": [
        "unselect_all",
        "reload"
    ],
    "style": "outline-dark"
}, {
    "name": "执行自定义脚本",
    "action": [
        "unselect_all",
        "script: delaycall",
        "script: 自定义脚本"
    ],
    "style": "outline-dark"
}]

会插入的自定义按钮如下:

2304-02.png

新增小工具 xresloader-dump-bin

虽然我们在使用 xresloader 转出数据的时候,可以设置多个输出,也导出一份json、lua、javascript等格式的配置以方便集成到Web或者其他周边工具中。也可以用于人工查看转出的数据。 但是我们项目中主要还是使用二进制格式,毕竟还是有些区别。为了方便查看实际的二进制数据,我新增了一个小工具 xresloader-dump-bin ,用于把protobuf格式的二进制直接转出为文本格式。 方便人工查阅,同时在发布更新资源版本的时候,为了方便使用diff工具查看变化的内容,我对输出的字段做了严格顺序的排序。

一个输出的示例如下:

# $ ./xresloader-dump-bin -p ./sample-conf/kind.pb -b ./sample-data/role_upgrade_cfg.bin

======================== Header: .\sample-data\role_upgrade_cfg.bin ========================
xresloader version: 2.8.0
data version: 2.8.0.20200609192757
data count: 11
hash code: sha256:718d22f78006e5d34d6b68eb56e204a00f4174737b6864e247b661d8963c7df3
description:
============ Body: .\sample-data\role_upgrade_cfg.bin -> role_upgrade_cfg ============
[
    {"Id": 10001, "Level": 1},
    {"Id": 10001, "Level": 2, "CostType": 10001, "CostValue": 50},
    {"Id": 10001, "Level": 3, "CostType": 10001, "CostValue": 100},
    {"Id": 10001, "Level": 4, "CostType": 10001, "CostValue": 150},
    {"Id": 10001, "Level": 5, "CostType": 10001, "CostValue": 200},
    {"Id": 10001, "Level": 6, "CostType": 10001, "CostValue": 250},
    {"Id": 10001, "Level": 7, "CostType": 10001, "CostValue": 300},
    {"Id": 10001, "Level": 8, "CostType": 10001, "CostValue": 350},
    {"Id": 10001, "Level": 9, "CostType": 10101, "CostValue": 400},
    {"Id": 10001, "Level": 10, "CostType": 10101, "CostValue": 450},
    {"Id": 10001, "Level": 11, "CostType": 10101, "CostValue": 500},
]

如果加 --pretty 选项可以进一步展开。diff的话比如可以如下输出:

$ git diff -a l.txt r.txt
diff --git a/l.txt b/r.txt
index 7ed0f3c..6f8d6fb 100644
--- a/l.txt
+++ b/r.txt
@@ -15,5 +15,6 @@ description:
     {"Id": 10001, "Level": 7, "CostType": 10001, "CostValue": 300},
     {"Id": 10001, "Level": 8, "CostType": 10001, "CostValue": 350},
     {"Id": 10001, "Level": 9, "CostType": 10101, "CostValue": 400},
-    {"Id": 10001, "Level": 10, "CostType": 10101, "CostValue": 500},
+    {"Id": 10001, "Level": 10, "CostType": 10101, "CostValue": 450},
+    {"Id": 10001, "Level": 11, "CostType": 10101, "CostValue": 500},
 ]

如果使用 vimdiff 或者其他编辑器的diff还能更好看一些。

读表代码生成工具-xres-code-generator增加 upb-lua binding支持

Protobuf有个子项目 upb ,这是一个纯C实现的非常小型的protobuf打解包运行时。现在包括Ruby、PHP和Python的binding也是它。 它内置有lua binding,我们项目组也是在尝试使用。

集成的过程中也是踩了点小坑,详情可参见: 《集成 upb 和 lua binding 的踩坑小记》

那么这里,我也是给upb的lua binding增加了读表的模板支持。得益于模板引擎的便利,实现起来非常简单,详见: https://github.com/xresloader/xres-code-generator/blob/main/template/DataTableCustomIndexUpb.lua.makohttps://github.com/xresloader/xres-code-generator/blob/main/template/common/upblua/DataTableServiceUpb.lua 。并且也支持多版本管理和多重索引。

最后

感谢大家的关注和贡献,欢迎持续交流拍砖。