You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在运行时按文件大小分割CSV并自动保存有效分片?

将CSV按1GB分片并动态保存所有分片的解决方案

问题场景

需要将CSV文件分割为1GB大小的分片,由于文件大小不固定,固定数量分割的方式不适用。已实现预估输出CSV大小和数据集分片逻辑,但不知道如何在运行时动态保存所有分片,避免生成空输出(例如原文件不足2GB时,不要生成第三分片)。已考虑despray操作但代码简化未包含,询问遗漏的实现点。

以下是在HPCC Systems Playground运行的原始代码:

STRING sInputFile := '~class::afca::crimes_-_2001_to_present.csv';
// Specification
modLayouts := MODULE
    EXPORT STRING sTerminator := '\n';
    EXPORT lLine := {STRING Line};
    EXPORT lTaggedLine := {lLine, UNSIGNED UpToSize, UNSIGNED Part};
END;
dInput := DATASET(sInputFile, modLayouts.lLine,
  CSV(HEADING(0),SEPARATOR(''),TERMINATOR(modLayouts.sTerminator),QUOTE(''),UNICODE)
);
// Header-Data split
dProduct := dInput[2..];
STRING sHeader := dInput[1].line + modLayouts.sTerminator;
// Split config
UNSIGNED uOneGigabyte := 1000000000;
UNSIGNED uGigabytesLimit := 1;
UNSIGNED uBytesLimit := uGigabytesLimit * uOneGigabyte;
UNSIGNED uByteCount(STRING sLine) := LENGTH(sLine)+LENGTH(modLayouts.sTerminator);
// Partition
dInputTagged := ITERATE(PROJECT(dProduct,TRANSFORM(modLayouts.lTaggedLine,SELF:=LEFT)),
     TRANSFORM(modLayouts.lTaggedLine,
        SELF.Line := RIGHT.Line,
        SELF.UpToSize := LEFT.UpToSize + uByteCount(RIGHT.Line),
        SELF.Part := IF(LEFT.Part=0,1,IF(SELF.UpToSize <= LEFT.Part*(uBytesLimit), LEFT.Part, LEFT.Part+1)),
        ),
     modLayouts.lTaggedLine{Part:=0, UpToSize:=0} // 明确初始值,避免默认值歧义
    );
// Results
SET OF UNSIGNED suParts := SET(SORT(TABLE(dInputTagged,{Part},Part,MERGE),Part),Part);
dPart(UNSIGNED uPart) := TABLE(dInputTagged(Part=uPart),{Line});
// Read outs
UNSIGNED uEstBytes := SUM(dInputTagged,uByteCount(dInputTagged.Line));
REAL rEstGigas := ROUND(uEstBytes/uOneGigabyte,2);
// Save and despray
aSavePartNum(UNSIGNED uPart) := FUNCTION
  RETURN IF(uPart IN suParts,
    OUTPUT(dPart(uPart),,sInputFile+'_pt'+uPart+'.csv',
           CSV(HEADING(SINGLE, sHeader),SEPARATOR(''),TERMINATOR('\n'),QUOTE(''),UNICODE)
           ,compressed,overwrite,expire(1),named('dPart_'+uPart)));
END;
// Outputs
OUTPUT(CHOOSEN(dInputTagged,1000), named('dInputTagged_sample'));
OUTPUT(sHeader,    named('sHeader'));
OUTPUT(rEstGigas,  named('rEstGigas'));
OUTPUT(uEstBytes,  named('uEstBytes'));
OUTPUT(suParts,    named('suParts'));
// 硬编码调用,导致可能生成空文件
aSavePartNum(1);
aSavePartNum(2);
aSavePartNum(3);

解决方案

核心问题

你当前硬编码调用了aSavePartNum(1);aSavePartNum(2);aSavePartNum(3);,这会强制尝试处理不存在的分片,进而生成空文件。解决思路是遍历实际存在的分片集合,动态触发保存操作。

修改步骤

  1. 移除硬编码的分片调用,替换为FOREACH遍历suParts集合:
// 遍历所有实际存在的分片,动态保存
FOREACH suParts AS uPart
    aSavePartNum(uPart);
END;
  1. (可选)优化ITERATE的初始值,明确指定初始的Part和UpToSize,避免默认值带来的逻辑歧义(已在上面的代码示例中修正)。

优化后效果

  • 只会处理suParts中存在的分片编号,完全根据原文件大小动态生成对应数量的分片,不会生成空文件。
  • 无论原文件是1.1GB、2.8GB还是更小,都能自动适配分片数量。

内容的提问来源于stack exchange,提问作者Emerson Grisi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.17 02:05:25