2011-10-27 158 views
5

我通常在C++中执行类似这样的操作,但是我使用python编写了一个快速脚本,并且遇到了一堵墙。Python中,如何将32位整数放入字节数组中

如果我有一个二进制列表(或任何python存储“fread”的结果)。我可以访问其中的单个字节:缓冲区[0],缓冲区[1]等。

我需要更改字节[8-11]来保存新的32位文件大小(读取:那里已经有一个文件大小,我需要更新它)。在C++中,我只是得到一个指向该位置的指针并将其转换为存储整数,但对于Python,我突然意识到我不知道如何做这样的事情。

如何更新我的缓冲区中的特定位置的4个字节以保存python中的整数值?

编辑

我要添加更多的,因为我似乎无法从解决方案看着办吧(虽然我可以看到他们是在正确的轨道上)。

首先,我使用的是Python 2.4(无法升级,大公司服务器) - 这显然限制了我的选择。对不起,之前没有提到,我不知道它有这么多的功能。

其次,让我们来做这个超简单的。

假设我有一个名为'myfile.binary'的二进制文件,其中包含十六进制的五字节内容'4C53535353' - 这等同于文件中单独的字母“L和4xS”的ASCII表示。

如果我做的:

f = open('myfile.binary', 'rb') 
contents = f.read(5) 

内容应该(从斯文Marnach的答案)举行的五字节的字符串不可改变。

只能使用Python 2.4的设施,我怎么能把'内容'中保存的4个S更改为任意整数值?即给我一行代码,可以使字节索引的内容[1-4]包含值为12345678910的32位整数'myint'。

+0

你不能因为字符串修改内容是不变的...你可以创造吃了一个新的字符串,或者使用像bytearray这样的可变容器。 – hochl

+0

谢谢,我很乐意创建一个新的字符串或字节数组,如果是这样的话。我怎么能创建一个可修改的字节数组与相同的contnets,并更新范围[1-4],以等于我的整数的二进制表示? –

+0

我在下面扩展了我的发帖,并包含了Python 2.4的一个工作示例:-) – hochl

回答

8

你需要的是这样的功能:

struct.pack_into(fmt, buffer, offset, v1, v2, ...) 

它在http://docs.python.org/library/struct.html接近顶部记录。

示例代码:

import struct 
import ctypes 

data=ctypes.create_string_buffer(10) 
struct.pack_into(">i", data, 5, 0x12345678) 
print list(data) 

类似的帖子:Python: How to pack different types of data into a string buffer using struct.pack_into

编辑:添加一个Python 2.4兼容的例子:

import struct 

f=open('myfile.binary', 'rb') 
contents=f.read(5) 
data=list(contents) 
data[0:4]=struct.pack(">i", 0x12345678) 
print data 
+1

+1。我建议使用内建的'bytearray'来创建可变缓冲区而不是'ctypes.create_string_buffer'。 –

+0

**对于所有人**,我尝试阅读包装页面和提供的解决方案。我似乎缺少很多,因为我有python 2.4而不是2.5。我在编辑上提供了一个我的问题的大大简化版本 - 如果你可以用一行代码来回答,我会完全开心:) –

+1

恐怕你的2.4兼容版本不能使用' bytearray',因为它是在2.6中引入的。 –

4

看看Struct模块。你需要pack函数。

编辑:

的代码:

import struct 

s = "LSSSS" # your string 
s = s[0] + struct.pack('<I', 1234567891) # note "shorter" constant than in your example 
print s 

输出:

L╙☻ЦI 

struct.pack应的python2.4可用。

你的号码“12345678910”不能打包成4个字节,我缩短了一下。

+0

*请参阅hochl的答案评论* –

+0

更新了答案 –

2

file.read()的结果是Python中的一个字符串,它是不可变的。根据您尝试完成的任务的环境,有不同的解决方案。

一个使用的是array module:直接以32位整数数组的形式读取文件。您可以修改此数组并将其写回文件。

with open("filename") as f: 
    f.seek(0, 2) 
    size = f.tell() 
    f.seek(0) 
    data = array.array("i") 
    assert data.itemsize == 4 
    data.fromfile(f, size // 4) 
data[2] = new_value 
# use data.tofile(g) to write the data back to a new file g 
+1

*请参阅hochl的回答评论* –

2

你可以安装numpy的模块,经常用于科学计算。

的read_data = numpy.fromfile(文件= ID,D型= numpy.uint32)

然后在需要的位置访问数据并进行更改。

+1

*请参阅hochl的回答评论* –

0

以下只是一个演示,用于了解将四个字节转换为整数时真正发生的情况。 假设有一个号码:15213

Decimal: 15213 
Binary: 0011 1011 0110 1101 
Hex: 3 B 6 D 

在小端系统(即x86上),这个数字可以使用长度为4字节组作为表示:b"\x6d\x3b\x00\x00"b"m;\x00\x00"打印时在屏幕上,四个字节转换为整数,我们只是做了一下基转换,在这种情况下,就是:

sum(n*(256**i) for i,n in enumerate(b"\x6d\x3b\x00\x00")) 

这给你一个结果:15213

相关问题