如何使用bash命令将csv转换为二进制文件?

时间:2016-06-03 11:51:40

标签: bash csv binaryfiles

我有一个csv文件,它只是一个以逗号分隔的简单数字列表。我想将此csv文件转换为二进制文件(只是一个字节序列,每个解释的数字都是csv文件中的数字。)

我这样做的原因是能够从值的电子表格导入音频数据。在我的导入(我使用的是audacity)中,我有几种格式可供选择,用于二进制文件:

Encoding:
Signed 8, 24, 16, or 32 bit PCM
Unsigned 8 bit PCM
32 bit or 64 bit float
U-Law
A-Law
GSM 6.10
12, 16, or 24 bit DWVW
VOX ADPCM

Byte Order:
No endianness
Big endian
Little endian

我正沿着big endian 32-bit float的路线前进,以保持简单。我想让事情变得尽可能简单,所以我认为bash将是最佳工具。

2 个答案:

答案 0 :(得分:3)

  

我有一个csv文件,它只是一个以逗号分隔的简单数字列表。我想将此csv文件转换为二进制文件[...]

     

我正沿着big endian 32-bit float的路线前进,以保持简单。

不确定如何在纯bash中执行此操作(实际上怀疑它是可行的,因为float as binary是非标准转换)。

但是这里有一个简单的Perl单线:

$ cat example1.csv
1.0
2.1
3.2
4.3

$ cat example1.csv | perl -ne 'print pack("f>*", split(/\s*,\s*/))' > example1.bin

$ hexdump -C < example1.bin
00000000  3f 80 00 00 40 06 66 66  40 4c cc cd 40 89 99 9a  |?...@.ff@L..@...|
00000010

它使用Perl的pack functionf将浮点数转换为二进制数,使用<将它们转换为BE。 (如果每行CSV行有多个数字,我也添加了拆分。)

P.S。将原子转换为16位短路的命令:

perl -ne 'print pack("s*", split(/\s*,\s*/))'

对BE使用"s>*",对LE使用"s<*",而不是"s*"

P.P.S。如果是音频数据,您还可以查看sox工具。多年来没有使用它,但IIRC它可以将任何类似PCM的任何格式转换为任何格式,同时也可以应用效果。

答案 1 :(得分:2)

我会推荐Python超过bash对于这个特定的任务,它更简单/更健全的IMO。

#!/usr/bin/env python

import array

with open('input.csv', 'rt') as f:
    text = f.read()
    entries = text.split(',')
    values = [int(x) for x in entries]
    # do a scalar here: if your input goes from [-100, 100] then
    #   you may need to translate/scale into [0, 2^16-1] for
    #   16-bit PCM
    # e.g.:
    #   values = [(val * scale) for val in values]

with open('output.pcm', 'wb') as out:
    pcm_vals = array.array('h', values) # 16-bit signed
    pcm_vals.tofile(out)

您也可以使用Python's wave module而不是仅编写原始PCM。

以上是上述示例的工作原理:

$ echo 1,2,3,4,5,6,7 > input.csv
$ ./so_pcm.py
$ xxd output.pcm
0000000: 0100 0200 0300 0400 0500 0600 0700       ..............

xxd显示二进制值。它使用了我机器的本机字节序(小)。