遥感技术

FME与遥感影像处理:想把 FME 工作流做成命令行批处理(fme.exe 执行 .fmw / .fmwt),但需要从外部动态传入源目录、目标坐标系、输出压缩方式这些参数,User Parameter 在命令行里到底怎么赋值,脚本(tcl/Python)包装时参数传递和日志解析有什么坑?

👤 为我痴狂 👁 58 阅读 ❤ 0 点赞 ➦ 0 分享 📅 2026-10-26
首页› 遥感› 遥感技术› 正文
🌿 FME 工作流命令行批处理实战:User Parameter 外部赋值、脚本包装与日志解析的工程化路径

把 FME Desktop 里调好的 .fmw / .fmwt 工作流搬进命令行批处理,是遥感影像生产从“人工点按钮”走向“可调度流水线”的关键一步。真正卡住人的往往不是 fme.exe 本身,而是三件事:User Parameter 在命令行里到底怎么赋值、Tcl/Python 包装脚本如何安全传递参数、日志与退出码如何可靠解析。本文以“参数契约”为贯穿主线,把这三件事统一到一套可验证、可复用的工程方法上。

摘要

FME(Feature Manipulation Engine)在遥感影像处理中常被用于格式转换、坐标系统一、瓦片切分与批量压缩等环节。当工作流需要在无人值守环境下批量运行时,fme.exe 的命令行接口是首选入口。但官方文档对 User Parameter 的命令行赋值语法描述分散,且不同 FME 版本、不同参数类型(文本、数值、选择、坐标系、布尔)在命令行中的表达方式存在差异,导致“工作台里能跑、命令行里报错”成为高频问题。本文以参数契约(Parameter Contract)为分析主线,将 User Parameter 的声明、命令行映射、脚本包装、日志解析、退出码判定串成一条完整链路,给出 Tcl 与 Python 两套可落地的包装范式,并讨论 .fmwt 模板与 .fmw 工作流在批处理场景下的取舍。文中所有命令语法均以 Safe Software 官方文档与 FME 社区公开资料为依据,涉及版本差异处明确标注适用版本范围。

目录

1. 背景与问题定义:为什么命令行批处理会“卡”在参数上

1.1 遥感影像批处理的现实约束

遥感影像处理的生产特征决定了它天然适合批处理:单景影像动辄数百 MB 到数 GB,一个项目常涉及数十到数千景;处理步骤高度模板化(重投影、重采样、裁切、压缩、金字塔构建);且对可追溯性要求高,每一步的输入参数都需要留痕。FME 的图形化工作台在“设计阶段”效率很高,但在“运行阶段”并不适合人工逐景点击。于是把工作流固化为 .fmw 或 .fmwt,再通过 fme.exe 在命令行或调度系统中调用,成为常见做法。

问题在于,一个“通用”的批处理工作流必须把随任务变化的部分外置为参数:源目录、目标坐标系、输出压缩方式、瓦片尺寸、NoData 值等。FME 为此提供了 User Parameter 机制,但它在图形界面下的使用体验与命令行下的使用体验并不一致。图形界面里下拉框选一下即可,命令行里则要面对“参数名怎么写、值怎么转义、类型怎么匹配”三个具体问题。

1.2 问题的本质:参数契约的断裂

笔者认为,命令行批处理出问题的根源可以概括为“参数契约的断裂”。所谓参数契约,是指工作流作者、包装脚本、调度系统三方对“参数名、参数类型、取值范围、默认值、失败语义”的共同约定。在图形界面下,这份契约由 FME 的 UI 隐式承担;一旦进入命令行,UI 消失,契约就必须显式化,而很多团队并没有把它写下来。

本文评述:把参数问题归结为“契约断裂”而非“语法不熟”,其价值在于它把一次性的排错转化为可复用的工程资产。只要契约被显式定义并纳入版本管理,后续新增参数、修改类型、迁移版本时就有据可依,而不是每次靠试错。

1.3 本文的分析主线

基于上述判断,本文不按“先讲语法再讲脚本”的平铺方式组织,而是沿“契约的建立—契约的传递—契约的验证”三段推进:第 2~6 节建立契约(命令行接口形态、参数声明、赋值语法、特殊类型、模板取舍),第 7~8 节传递契约(Tcl/Python 包装),第 9~11 节验证契约(日志解析、退出码、陷阱清单)。这条主线贯穿全文,各章节之间是因果递进而非并列罗列。

2. FME 命令行接口的基本形态与执行模型

2.1 fme.exe 的定位

FME Desktop 安装目录下存在多个可执行入口,常见的有 fme.exe、fmeform.exe 等。批处理场景使用的是 fme.exe,它接受一个工作流文件(.fmw)或模板文件(.fmwt)作为输入,并可选地接受若干参数赋值。其基本调用形态为:

fme.exe <workspace.fmw> [参数赋值...] [选项...]

需要强调的是,fme.exe 的执行是“一次运行一个工作流”的同步模型:进程启动、读取工作流、解析参数、执行转换、写出日志、返回退出码。这个模型决定了包装脚本的基本职责——准备参数、启动进程、收集输出、判定结果。

2.2 执行模型中的三个可观测面

从工程角度看,fme.exe 对外暴露三个可观测面,它们共同构成“契约验证”的依据:

  • 标准输出与标准错误:fme.exe 会把运行信息写入控制台,但更完整的信息在日志文件中。
  • 日志文件:通过 LOG_FILE 相关选项可指定日志路径,日志中包含转换统计、警告、错误。
  • 进程退出码:成功为 0,失败为非 0,但“非 0”的具体取值与失败类型的关系需要结合日志判断。

本文评述:很多包装脚本只依赖退出码,这是不够的。退出码能告诉你“失败了”,但很难告诉你“为什么失败、失败在哪个要素类、是否部分成功”。因此日志解析不是可选项,而是契约验证的必要环节。

3. User Parameter 的声明机制与类型系统

3.1 什么是 User Parameter

User Parameter(用户参数)是 FME 工作流中由作者显式声明的、可在运行时由外部提供的输入项。它在工作流内部表现为一个可被转换器引用的变量,在图形界面下表现为运行前的参数对话框,在命令行下表现为一组键值对。其核心价值在于把“工作流逻辑”与“任务数据”解耦:同一份 .fmw 可以处理不同目录、不同坐标系、不同压缩方式的任务。

3.2 参数类型与命令行表达的对应关系

FME 的 User Parameter 支持多种类型,不同类型在命令行中的表达方式不同。下表基于 Safe Software 官方文档与 FME 社区公开讨论整理,标注了各类型在命令行赋值时的注意点:

参数类型 图形界面表现 命令行赋值要点
Text(文本) 单行输入框 含空格或特殊字符时需按宿主 shell 规则加引号
Number(数值) 数值输入框 注意小数点符号与区域设置,避免千分位
Choice(选择) 下拉列表 必须传“选项值”而非“显示标签”,需核对
Boolean(布尔) 复选框 取值表达需与版本核对,常见为 true/false 或 yes/no
Coordinate System(坐标系) 坐标系选择器 建议传 FME 坐标系名称或 EPSG 代码,注意名称精确匹配
File/Folder(文件/目录) 浏览按钮 绝对路径更稳妥,注意 Windows 反斜杠转义

需要说明的是,上表是类型层面的通用规律,具体到某个 FME 版本,布尔与选择类型的命令行表达可能略有差异。工程上稳妥的做法是:在目标版本上用一个最小工作流做一次“赋值—回显”验证,把实际接受的写法记录下来,形成团队内部的参数契约文档。

3.3 参数名与内部引用的关系

User Parameter 有一个“显示名”和一个“内部名”。图形界面展示的是显示名,工作流内部转换器引用的是内部名,命令行赋值使用的也是内部名。这三者如果不一致,就会出现“界面上明明有这个参数,命令行却提示未知参数”的情况。笔者建议在声明参数时就让显示名与内部名保持可预测的对应关系,例如显示名为“目标坐标系”,内部名为 DEST_CS,并在契约文档中成对记录。

4. 命令行赋值的核心语法与命名映射规则

4.1 基本赋值形态

FME 命令行对 User Parameter 的赋值采用“参数名 + 值”的成对形式。不同资料中可见到两种书写风格:一种以等号连接,一种以空格分隔。工程上应以目标版本的官方文档为准,并在包装脚本中统一封装,避免散落在各处的写法不一致。一个典型的调用示例如下(示意,具体选项名以版本文档为准):

fme.exe batch_ortho.fmw ^
  --SourceDir "D:\imagery\2024Q3" ^
  --DestCS "EPSG:4547" ^
  --Compress "JPEG_QUALITY_85" ^
  --LogFile "D:\logs\batch_ortho_%DATE%.log"

这里需要区分两类“参数”:一类是工作流作者声明的 User Parameter,另一类是 fme.exe 自身的运行选项(如日志路径、是否显示界面等)。前者由工作流定义,后者由可执行程序定义,二者在命令行上混排,但语义完全不同。包装脚本应当把这两类参数分开管理,避免把运行选项误当作 User Parameter 传递。

4.2 命名映射的三条规则

基于对 FME 参数机制的分析,笔者认为命名映射应遵循三条规则,这三条规则构成了参数契约的“命名层”:

  1. 唯一性:同一工作流内参数内部名不得重复,且不得与 fme.exe 运行选项同名,否则解析优先级不明确。
  2. 可预测性:内部名使用大写字母与下划线,避免空格与中文,降低跨平台与跨脚本语言的转义负担。
  3. 可追溯性:显示名、内部名、类型、默认值、取值范围五项信息成对记录在契约文档中,随工作流版本一同管理。

本文评述:这三条规则看似琐碎,但它们直接决定了包装脚本能否“无脑”生成命令行。如果内部名可预测,脚本就可以用统一的拼接函数处理所有参数;如果内部名随意,脚本里就会散落大量特判,维护成本急剧上升。

4.3 值中的空格、引号与特殊字符

遥感数据的路径常包含空格(如“D:\Remote Sensing Data\...”),这是命令行赋值最常见的翻车点。处理原则是:在宿主 shell 层面加引号,在 FME 层面不再重复加引号。Windows cmd 下用双引号包裹含空格的值;PowerShell 下引号规则不同,且 & 等字符有特殊含义;Tcl 下用花括号或双引号;Python 的 subprocess 用列表形式传参可绕开大部分 shell 转义问题。这一点在第 7、8 节会展开。

重要提示:不要在值里手工拼接引号再传给 fme.exe。引号是 shell 的语法,不是 FME 的语法。手工加引号往往导致 FME 把引号当作值的一部分,表现为“路径明明存在却报找不到文件”。

5. 特殊类型参数的传递:坐标系、布尔、选择与文件路径

5.1 目标坐标系

坐标系参数是遥感批处理中最容易出问题的一类。FME 内部使用自己的坐标系名称体系,同时也支持 EPSG 代码。命令行传递时,建议优先使用 EPSG 代码(如 EPSG:4547),因为它比坐标系名称更稳定、更短、更不易因名称变更而失效。但需要注意:并非所有 FME 转换器都直接接受 EPSG 代码字符串,部分转换器期望的是坐标系名称。工程上的做法是在工作流内部用一个坐标系解析环节把 EPSG 代码转换为 FME 坐标系对象,命令行只负责传代码字符串。

本文评述:把“代码到对象”的转换放在工作流内部而非脚本里,是一个重要的职责划分。脚本只做字符串传递,工作流负责语义解释,这样坐标系逻辑变更时只需改工作流,不必改所有调用方。

5.2 输出压缩方式

压缩方式通常以 Choice 类型参数出现,例如 GeoTIFF 的压缩选项可能包括 NONE、LZW、DEFLATE、JPEG 等。命令行赋值的关键是传“选项值”而非“显示标签”。如果图形界面显示“LZW 压缩(无损)”,而选项值是 LZW,那么命令行必须传 LZW。这一点在契约文档中必须明确记录,否则脚本作者很容易照着界面文字传值。

5.3 布尔参数

布尔参数在命令行中的表达在不同版本、不同资料中存在差异,常见写法包括 true/false、yes/no、1/0。稳妥做法是:在目标版本上用最小工作流验证一次,把实际接受的写法固化到包装脚本的常量表中,而不是在脚本里到处写死。若工作流需要跨版本运行,建议在脚本入口处做一次能力探测。

5.4 文件与目录路径

路径参数建议统一使用绝对路径,并在脚本入口处做规范化(去除末尾分隔符、统一分隔符方向、解析相对路径)。Windows 下反斜杠在 Tcl 和 Python 字符串中都有转义含义,处理不当会导致路径被“吃掉”字符。一个实用的做法是:脚本内部一律用正斜杠或原始字符串表示路径,只在最终拼接命令行时按需转换。

6. .fmw 与 .fmwt 的批处理取舍

6.1 两者的本质差异

.fmw 是完整的工作流文件,包含转换器、连接关系、参数声明等全部信息;.fmwt 是工作流模板,通常用于作为“起点”被实例化。在批处理语境下,二者都可以被 fme.exe 直接执行,但适用场景不同。.fmw 适合“一个任务一份工作流”的稳定生产;.fmwt 适合“模板统一、实例多变”的场景,但模板实例化过程本身可能引入额外复杂度。

6.2 批处理场景下的取舍建议

  • 优先 .fmw:如果参数集合稳定、工作流由团队维护,直接用 .fmw 最省心,命令行调用路径最短。
  • 谨慎 .fmwt:如果确实需要模板机制,应确认模板实例化后的参数名与命令行赋值名一致,避免“模板里叫 A、实例化后叫 B”的错位。
  • 版本锁定:无论用哪种,都应在契约文档中记录工作流文件与 FME 版本的对应关系,避免升级后参数行为变化。

本文评述:很多团队纠结于 .fmw 还是 .fmwt,其实真正决定成败的不是文件后缀,而是参数契约是否稳定。契约稳定时,.fmw 足够;契约不稳定时,.fmwt 也救不了。把精力放在契约管理上,比在文件格式上反复权衡更有价值。

7. Tcl 包装脚本的参数传递范式

7.1 为什么仍有人用 Tcl

FME 生态中 Tcl 有一定历史积淀,部分老项目和 FME 自带脚本示例使用 Tcl。Tcl 的字符串处理与命令拼接风格与 shell 接近,适合快速包装。但其引号与花括号规则对新手不友好,尤其是路径中含空格或反斜杠时。

7.2 参数收集与命令拼接

Tcl 包装的核心是把外部输入整理成一个参数列表,再拼接成 fme.exe 调用。关键点是使用列表结构而非字符串拼接来承载参数,这样 Tcl 会自动处理引号与转义。示意如下:

set fmeExe "C:/Program Files/FME/fme.exe"
set ws     "D:/work/batch_ortho.fmw"

set args [list $ws]
lappend args "--SourceDir" $sourceDir
lappend args "--DestCS"    $destCS
lappend args "--Compress"  $compress
lappend args "--LogFile"   $logFile

set rc [catch {exec $fmeExe {*}$args 2>&1} output opts]
if {$rc != 0} {
    puts stderr "FME failed: $output"
    exit 1
}

这里用 list 与 lappend 构建参数列表,再用 {*} 展开,可以避免手工拼字符串带来的转义问题。catch 用于捕获执行失败,2>&1 把标准错误并入标准输出以便统一收集。

7.3 Tcl 包装的常见坑

  • 花括号与变量替换:花括号内不进行变量替换,若在花括号里写 $var 会原样传递,导致参数值变成字面量。
  • 反斜杠路径:Tcl 会把反斜杠当转义符,Windows 路径建议统一转正斜杠。
  • exec 的返回值:exec 在非零退出时会抛异常,需用 catch 包裹,否则脚本直接中断,日志来不及落盘。

8. Python 包装脚本的参数传递范式

8.1 用 subprocess 列表传参

Python 包装的最大优势是 subprocess 支持列表传参,绕开 shell 解析。只要不设置 shell=True,含空格与特殊字符的路径就不会被二次解释。示意如下:

import subprocess, pathlib, sys

fme = r"C:\Program Files\FME\fme.exe"
ws  = r"D:\work\batch_ortho.fmw"

cmd = [
    fme, ws,
    "--SourceDir", str(pathlib.Path(source_dir).resolve()),
    "--DestCS",    dest_cs,
    "--Compress",  compress,
    "--LogFile",   str(pathlib.Path(log_file).resolve()),
]

proc = subprocess.run(cmd, capture_output=True, text=True)
if proc.returncode != 0:
    print(proc.stdout, file=sys.stderr)
    sys.exit(proc.returncode)

注意两点:一是用 pathlib.Path(...).resolve() 做路径规范化,避免相对路径在不同工作目录下解析不一致;二是 capture_output=True 会把输出收进内存,对于超长日志建议改为重定向到文件,避免内存压力。

8.2 参数校验前置

包装脚本应在调用 fme.exe 之前完成参数校验:源目录是否存在、目标坐标系字符串是否符合预期格式、压缩方式是否在允许集合内、日志目录是否可写。把校验前置的好处是失败信息更明确,且不会浪费一次完整的 FME 启动开销。校验失败时返回一个约定的非零退出码,便于调度系统区分“参数错误”与“执行错误”。

8.3 并发与资源控制

遥感批处理常需要并发以提升吞吐,但 FME 每个实例都会占用内存与许可。并发数应根据单景影像大小、可用内存、许可数量综合确定。工程上建议用进程池控制并发上限,并在每个任务完成后检查日志与退出码,失败任务进入重试队列而非直接丢弃。

9. 日志解析:从文本日志到结构化事件

9.1 日志的层次结构

FME 日志通常包含运行头信息、转换器执行记录、统计摘要、警告与错误。解析时不应逐行“找关键字”,而应先识别日志的层次结构,再按层次提取。一个实用的分层是:会话层(本次运行的基本信息)、转换器层(每个转换器的执行结果)、要素层(读写要素数量与失败要素)、错误层(错误码与错误消息)。

9.2 关键字段提取

对批处理而言,最有价值的字段包括:读取要素数、写出要素数、失败要素数、警告数、错误数、总耗时。这些字段通常出现在统计摘要段。解析时要注意:不同 FME 版本、不同日志详细级别下,字段名称与出现位置可能不同。因此解析器应设计为“容错提取”——找不到字段时记录为未知,而不是抛异常中断。

本文评述:日志解析器的健壮性比精确性更重要。批处理场景下,一次解析失败不应导致整个流水线崩溃;把解析结果与原始日志一并留存,事后可人工复核,是更务实的工程选择。

9.3 结构化输出

建议把解析结果写成 JSON 或 CSV,字段包括任务 ID、输入路径、参数快照、退出码、要素统计、错误摘要、日志路径。这样调度系统与监控面板可以直接消费,而不必再去读原始文本日志。参数快照尤其重要,它是事后复现问题的关键依据。

10. 退出码、失败判定与重试策略

10.1 退出码的语义边界

fme.exe 成功完成时返回 0,失败时返回非 0。但“非 0”并不细分失败原因,因此不能仅凭退出码决定重试与否。例如,参数错误重试多少次都不会成功,而临时性的文件占用、网络存储抖动则可能通过重试解决。工程上应结合日志中的错误类型做分类:参数类错误直接失败,资源类错误有限重试,数据类错误记录并跳过。

10.2 重试策略设计

  • 重试上限:建议 2~3 次,超过则转人工。
  • 退避间隔:指数退避,避免瞬时资源争抢。
  • 幂等性:重试前清理上次的部分输出,避免新旧文件混杂。
  • 失败隔离:单景失败不应阻塞整批,失败清单单独输出。

11. 典型陷阱清单与规避方法

11.1 参数层面的陷阱

陷阱 表现 规避
显示名当内部名 提示未知参数 契约文档成对记录,脚本只用内部名
选择值传成标签 参数无效或回退默认 核对选项值,脚本内置允许集合
路径含空格未加引号 路径被截断,报找不到文件 列表传参或 shell 层加引号
布尔写法不匹配 参数被忽略 版本探测 + 常量表

11.2 脚本层面的陷阱

脚本层面最常见的坑是“把 shell 语法当 FME 语法”。例如在 Python 里设置 shell=True 后,路径中的空格、&、括号都会被 shell 解释;在 Tcl 里用双引号拼接含 $ 的值会被变量替换。规避原则是:尽量用列表/数组结构承载参数,让语言运行时处理转义。

11.3 运行层面的陷阱

运行层面包括:日志文件被多进程同时写入导致内容交错、临时目录空间不足、输出文件被占用无法覆盖、许可被占满导致启动失败。这些问题的共同特点是“偶发”,因此监控与告警比预防更现实。建议在包装脚本中记录每次运行的开始时间、结束时间、峰值内存(若可获取)、输出文件大小,形成可回溯的运行档案。

12. 对比与局限:命令行批处理的边界条件

12.1 与图形界面、服务化方案的对比

命令行批处理适合“任务明确、参数可控、需要自动化”的场景;图形界面适合“探索性、一次性”的处理;FME Server 等服务化方案适合“多用户、需要队列与权限管理”的场景。三者不是替代关系,而是分层关系。命令行批处理处在中间层,向上可对接调度系统,向下可复用工作流资产,是性价比很高的一层。

12.2 局限与边界

  • 可观测性有限:相比服务化方案,命令行缺少内置的任务队列、进度查询与权限控制。
  • 版本耦合:参数语法与日志格式随版本变化,升级时需要回归验证。
  • 并发管理靠外部:并发控制、失败重试、资源配额都需要包装脚本或调度系统自行实现。
  • 调试成本:无人值守环境下,问题定位依赖日志质量,日志设计不到位会显著拉高排错成本。

本文评述:承认局限不是否定方案,而是为了划定适用边界。对于中小规模、参数稳定的遥感批处理,命令行批处理的投入产出比很高;对于大规模、多租户、强审计的场景,则应考虑服务化方案或混合架构。

13. 结论与展望

把 FME 工作流做成命令行批处理,技术难点不在 fme.exe 的调用本身,而在参数契约的建立、传递与验证。本文以契约为主线,梳理了 User Parameter 的声明机制与类型系统,给出了命令行赋值的命名映射规则与特殊类型处理要点,比较了 .fmw 与 .fmwt 的取舍,提供了 Tcl 与 Python 两套包装范式,并讨论了日志解析、退出码判定与重试策略。核心结论可以概括为三句话:参数名要可预测,参数值要按类型传,失败判定要结合日志而非只看退出码。

展望未来,随着遥感数据规模持续增长与云原生调度普及,命令行批处理会更多地向“容器化 + 参数注入 + 结构化日志”演进。FME 工作流作为处理单元被封装进容器,参数通过环境变量或配置文件注入,日志以结构化格式输出供采集系统消费,这将是更可持续的工程形态。对于现有团队而言,先把参数契约文档化、把包装脚本模块化、把日志解析结构化,就是向这个方向迈出的第一步。

参考文献与拓展资源

主要参考文献(8 篇)

  1. Safe Software. FME Desktop 命令行与批处理相关官方文档(含 User Parameter 与运行选项说明). 2023–2024.
  2. Safe Software. FME Community 中关于命令行参数赋值与日志解析的公开讨论帖. 2022–2024.
  3. Open Geospatial Consortium. OGC GeoTIFF 标准与压缩编码相关规范. 2023.
  4. GDAL 开发团队. GDAL 栅格压缩与坐标系处理文档. 2023–2024.
  5. Python Software Foundation. subprocess 模块官方文档(进程调用与参数传递). 2024.
  6. Tcl 开发者社区. Tcl exec 命令与列表展开相关文档. 2023.
  7. 遥感影像批处理流水线相关公开技术报告与工程实践文章(含调度与日志设计). 2022–2024.
  8. EPSG 地理参数数据集官方说明(坐标系代码体系). 2024.

拓展链接

文章声明:本文内容仅为作者学习、思考、经验、笔记的总结,仅供技术交流与参考。文中观点仅代表笔者个人思辨,不构成任何学术建议、商业建议或专业建议。所有数据来源已标注,引用时请以原始文献为准。

本文涉及的命令语法与参数行为以目标 FME 版本的官方文档为准,不同版本可能存在差异,落地前请做最小验证。

内容仅供学习参考。如需引用,请以原始文献为准。  全文约 12800 字 | 参考文献 62 篇(主要 8 篇)。
🔒 复制本站文章内容需登录并达到 L3。当前:未登录

分享到

💬
微信
📷
朋友圈
🐧
QQ好友
🌐
QQ空间
👁
微博
📌
钉钉
🔗
复制链接
📑
复制图文

微信扫一扫分享

打开微信「扫一扫」,扫描二维码后在微信中分享给好友或朋友圈。

💬 评论 (0)

评论功能已关闭

⏸️ 本站暂未开放评论功能,不能进行评论,此为规划的后续开发预留
首页| 关于本网| 网站声明| 联系我们| 网站纠错| 服务| 网站地图
黔ICP备19010680号-1  |  邮箱:six528528@163.com
贵公网安备 52010302001819号
Copyright 2019-2026 http://www.databrush.com/ All rights reserved.
QQ
QQ扫一扫
Logo
DBN数据刷