读取 python 中的二进制数据(替换 C 代码)

Reading binary data in python (to replace C code)

我正在编写一个 python 程序来替换一个 C 程序,除其他外,该程序从微控制器接收数据。这是在 C 语言中使用简单的套接字和读取函数完成的。在我的 python 程序中,我能够从微控制器读取一串数据,但我似乎无法将其转换为可读格式。我捕获了这个字符串并编写了一个小得多的程序,试图将它转换成一个数字列表:

import array
import thread
import socket
import time
import math
import numpy as np
import struct

data = open("rawfile.txt", 'r')
conv = open("conv.bin", 'wb')
pack = open("pack.txt", 'w')


# This line reads in the data string from the file
rawdata = data.read()

length = len(rawdata)

unpack = np.zeros(length, dtype=np.int64)
inter = np.int64

size = 4
m=0

for n in range(0,length-size):
    inter = struct.unpack_from('h',rawdata,n)
    unpack[m] = inter[0]
    m=m+1
    n=n+4

conv.write(unpack)
for j in range(0,len(unpack)):
    #print unpack[j]
    stringtowrite = str(unpack[j])
    pack.write(stringtowrite)
    pack.write(',')

#conv.write(dat2)
print "Done"

这是该程序生成的数据(在 Matlab 中绘制),以及数据应该是什么样子:(清洁脉冲应该是什么样子)

任何帮助将不胜感激,我已经为此苦苦挣扎了数周。我可以上传原始数据文件,但我不确定如何上传,因为它太大了。

所以总而言之,我的问题是为什么程序会为第一张图片而不是第二张图片生成数据,我读取和转换数据的方式是否有明显的错误。

提前致谢!

EDIT/UPDATE:

感谢下面的精彩回答,我现在正在使用这个:

dt = np.dtype('int16')
unpack = np.zeros(302000, dtype=dt)
unpack = np.fromfile(data, dtype=dt)

conv.write(unpack)

而且数据看起来更好!第一张图片使用 dtype('int16'),第二张图片使用 dtype('int32')。我还发现我正在读取的数据由交替的 real/imaginary 数字组成,这是否应该更改我用于 numpy dtype 的格式字符串?据我所知,C 代码中没有任何步骤可以解决这个问题。

最终更新:

为了避免其他人混淆,上面的后两张图片正确读取了数据,这是实际数据中的一个问题导致它们看起来不正确。

由于实际数据看起来是垂直量化的,您可能交换了字节顺序。

尝试unpack[m] = (inter[0] % 0x100) * 0x100。如果这看起来不错,您必须使用不同的字节顺序解压缩数据。

这里有多个问题。

您正在遍历字节数据,但将该数据解释为 2 字节单位。 offset是以字节为单位的偏移量,而不是以fmt为单位的偏移量。所以数据是这样布局的(数字是整数的索引):

1 1 2 2 3 3 4 4 5 5 6 6

但是你是这样读取数据的:

1 1  
  1 2
    2 2
      2 3
        3 3
          3 4
            4 4
              4 5
                5 5
                  5 6
                    6 6

而不是像这样:

1 1
    2 2
        3 3
            4 4
                5 5
                    6 6

您需要使用 range(0, length-size, 2) 以步长 2 进行迭代。

但是,Python 范围是半开的,它们不包括最后一个值。所以你正在放弃目前的最后一个样本。如果您不想这样做,请不要使用 -size.

然而,这不是遍历字节的惯用方式。更好的方法是直接迭代它们:

for idata in rawdata[::2]:

这将迭代字节对。

但如果您已经在使用 numpy,那么这是一种迂回的方式。 numpy 有一种非常快速的方法可以从二进制数据中解压整个数组:fromstring。您可以像这样一次读入所有数据:

unpack = np.fromstring(data.read(), dtype=np.int16)

此外,您的 size 或格式错误,h 是 2 个字节,但 size 是 4 个字节。此外,您正在隐藏内置 size 函数。使用不同的变量名称。

此外,这是作为二进制数据处理的,因此您应该以二进制方式打开文件。如果这样做,您可以以相同的方式使用 numpy 的 fromfile,但不必先执行 read,这样会更快:

unpack = np.fromfile(data, dtype=np.int16)