【问题标题】:What is the fastest method to write blocks of data from a huge file to a new file?将数据块从大文件写入新文件的最快方法是什么?
【发布时间】:2023-03-21 02:31:01
【问题描述】:

假设我有一个文件,它只是重复非常相似的块(如下所示的简化示例)。提取某些块并将它们写入单独的文件的最快方法是什么?所有块都以相同的编号 \n 开头。输入文件可以有超过一百万个步骤,每个块可以是几千个原子。因此,我不想读取(巨大的)文件或完全循环它,因为我只需要有限数量的步骤(例如每 1000 步)。我正在考虑使用 bash 脚本(sed 或 head|tail 分组)、python(内存映射和使用正则表达式存储块)或 awk(Write blocks in a text file to multiple new files)。有没有我不知道的方法或语言? 谢谢

6
step 1
C                  9.0000000    8.3380808    9.0000001
C                  9.0000000    9.6619194    8.9999999
H                  8.0768455    7.7678700    9.0000001
H                  9.9231545   10.2321301    9.0000001
H                  8.0768455   10.2321301    9.0000001
H                  9.9231545    7.7678700    9.0000001
6
step 2
 C                  9.00000000    8.33808080    9.00000010
 C                  9.00000000    9.66191940    8.99999990
 H                  8.07684550    7.76787000    9.00000010
 H                  9.90912982   10.23213008    8.83969637
 H                  8.09087028   10.23213012    9.16030383
 H                  9.92315450    7.76787000    9.00000010
6
step 3
 C                  9.00000000    8.33808080    9.00000010
 C                  9.00000000    9.66191940    8.99999990
 H                  8.07684550    7.76787000    9.00000010
 H                  9.86748170   10.23213006    8.68426301
 H                  8.13251850   10.23213014    9.31573717
 H                  9.92315450    7.76787000    9.00000010

【问题讨论】:

  • minimal reproducible example,你对任务的描述并没有真正的帮助
  • 如果每个块的字节数相同,您可以mmap文件并计算您需要的每个块的开始和结束。在那里寻找,读取确切的字节数并为每个块重复。如果字节数不同......那么你将不得不遍历整个文件。
  • 如果块的大小都相同,可能与dd 相关?
  • 我只需要有限数量的步骤您能否显示所提供示例数据的预期输出?另外,那些\ns 是字符串还是换行符?在后一种情况下,不需要在示例数据中显示它们,请将它们编辑掉。
  • 6是后面block的数据行数吗?

标签: python-3.x awk bigdata


【解决方案1】:

我在awk 中写了一个小 POC。这接近你想要的吗?

awk '
  /^[0-9]/ { print "skipping " $0; next; }
  /step /  { fn = sprintf("%s.%s", $1, $2); print "assigned fn = ", fn; }
  /^ *[A-Z]/ { print $0 >> fn; print "sent ", $0, " to ", fn; }
' infile

输出:

skipping 6
assigned fn =  step.1
sent  C                  9.0000000    8.3380808    9.0000001  to  step.1
sent  C                  9.0000000    9.6619194    8.9999999  to  step.1
sent  H                  8.0768455    7.7678700    9.0000001  to  step.1
sent  H                  9.9231545   10.2321301    9.0000001  to  step.1
sent  H                  8.0768455   10.2321301    9.0000001  to  step.1
sent  H                  9.9231545    7.7678700    9.0000001  to  step.1
skipping 6
assigned fn =  step.2
sent   C                  9.00000000    8.33808080    9.00000010  to  step.2
sent   C                  9.00000000    9.66191940    8.99999990  to  step.2
sent   H                  8.07684550    7.76787000    9.00000010  to  step.2
sent   H                  9.90912982   10.23213008    8.83969637  to  step.2
sent   H                  8.09087028   10.23213012    9.16030383  to  step.2
sent   H                  9.92315450    7.76787000    9.00000010  to  step.2
skipping 6
assigned fn =  step.3
sent   C                  9.00000000    8.33808080    9.00000010  to  step.3
sent   C                  9.00000000    9.66191940    8.99999990  to  step.3
sent   H                  8.07684550    7.76787000    9.00000010  to  step.3
sent   H                  9.86748170   10.23213006    8.68426301  to  step.3
sent   H                  8.13251850   10.23213014    9.31573717  to  step.3
sent   H                  9.92315450    7.76787000    9.00000010  to  step.3

结果文件:

$: cat step.1
C                  9.0000000    8.3380808    9.0000001
C                  9.0000000    9.6619194    8.9999999
H                  8.0768455    7.7678700    9.0000001
H                  9.9231545   10.2321301    9.0000001
H                  8.0768455   10.2321301    9.0000001
H                  9.9231545    7.7678700    9.0000001
$: cat step.2
 C                  9.00000000    8.33808080    9.00000010
 C                  9.00000000    9.66191940    8.99999990
 H                  8.07684550    7.76787000    9.00000010
 H                  9.90912982   10.23213008    8.83969637
 H                  8.09087028   10.23213012    9.16030383
 H                  9.92315450    7.76787000    9.00000010
$: cat step.3
 C                  9.00000000    8.33808080    9.00000010
 C                  9.00000000    9.66191940    8.99999990
 H                  8.07684550    7.76787000    9.00000010
 H                  9.86748170   10.23213006    8.68426301
 H                  8.13251850   10.23213014    9.31573717
 H                  9.92315450    7.76787000    9.00000010

请注意,您的示例在第一部分没有前导空格,但在后续部分有一个。

根据需要调整,希望对您有所帮助。

【讨论】:

  • 这当然解决了问题,但没有回答问题哪种方法最快?
  • 读取文件一次并在执行过程中处理任务的东西通常比必须经过多次传递的东西要快。假设纯bash 使用readawk 之类的东西将比bash 脚​​本更快。与管道并行运行多个可执行文件可能会获得更快的结果,但 head|tail 必须一遍又一遍地执行才能获得所有部分,所以不要这样做。如果您只是要写入文件,我认为内存映射几乎没有价值。我对 最快 的回答在我的示例中是隐含的 - 抱歉不清楚。
猜你喜欢
  • 2012-04-22
  • 1970-01-01
  • 2020-09-01
  • 1970-01-01
  • 2015-02-07
  • 2020-10-06
  • 1970-01-01
  • 2010-10-12
  • 2010-11-06
相关资源
最近更新 更多