读取 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)
我正在编写一个 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)