包装二进制数据文件以自我转换为CSV?

时间:2012-01-31 04:52:39

标签: bash gcc binary-data

我正在为SparkFun Logomatic V2编写自定义固件,它将二进制数据记录到2GB micro-SD卡上的文件中。数据文件大小范围为100 MB到1 GB。

随着电路板固件的发展,二进制数据的格式不断变化(实际上它将在运行时动态重新配置)。我不是为每个版本的固件/配置创建和维护单独的解码器/转换器程序,而是通过使用写入数据文件的Bash脚本启动数据文件,使数据文件自我转换为CSV格式在数据记录开始之前。

我知道如何创建Here Document,但我怀疑Bash无法快速解析和转换一个GB的二进制数据,因此我希望通过让脚本首先编译一些C来使进程运行得更快代码(假设存在GCC并在路径中),然后运行生成的程序,将二进制数据传递给stdin。

为了使问题更具体,假设固件将创建由4个16位整数值组成的二进制数据:时间戳(无符号),后跟3个加速度计轴(带符号)。记录之间没有分隔符(主要是因为我使SPI接口与uSD卡饱和)。

所以,我认为我需要一个带有TWO脚本的脚本:一个用于C代码(由扩展的Bash变量参数化),另一个用于二进制数据。这是我到目前为止的地方:

#! env bash
# Produced by firmware version 0.0.0.0.0.1 alpha
# Configuration for this data run:
header_string = "Time, X, Y, Z"
column_count = 4
# Create the converter executable
# Use "<<-" to permit code to be indented for readability.
# Allow variable expansion/substitution.
gcc -xc /tmp/convertit - <<-THE_C_CODE
    #include <stdio.h>
    int main (int argc, char **argv) {
        // Write ${header_string} to stdout
        while (1) {
            // Read $(column_count} shorts from stdin
            // Break if EOF
            // Write $(column_count} comma-delimited values to stdout
        }
        // Close stdout
        return 0;
    }
THE_C_CODE
# Pass the binary data to the converter
# Hard-quote the Here tag to prevent subsequent expansion/substitution
/tmp/convertit >./$1.csv <<'THE_BINARY_DATA'
...
... hundreds of megabytes of semi-random data ...
...
THE_BINARY_DATA
rm /tmp/convertit
exit 0

看起来对吗?我还没有真正的数据文件来测试这个,但我想在进一步研究之前验证这个想法。

如果关闭线丢失,Bash会抱怨吗?如果数据捕获由于电池或uSD卡松动而导致意外终止,则可能会发生这种情况。或者如果固件borks。

我应该考虑更快或更好的方法吗?例如,我想知道Bash是否太慢而无法像C程序那样快速地复制二进制数据:C程序应该直接打开数据文件吗?

TIA,

-BobC

1 个答案:

答案 0 :(得分:1)

您可能需要查看makeself。它允许您将任何.tar.gz存档更改为独立于平台的自解压文件(类似于包含此文档的shell脚本)。这样您就可以轻松分发数据和解码器。它还允许您配置存档中包含的脚本,以便在运行容器脚本时运行。通过这种方式,您可以使用makeself进行打包,在存档中,您可以将您的数据文件和解码器用C或bash或您认为合适的任何语言编写。

虽然可以使用shell工具解码二进制数据(例如使用od),但它非常麻烦且无效。我建议使用C程序或perl,它几乎可以在任何机器上找到(检查this page)。