2011-10-27 73 views
5

Tôi thường thực hiện những việc như thế này trong C++, nhưng tôi đang sử dụng python để viết kịch bản nhanh và tôi đã chạy vào tường.Python, cách đặt số nguyên 32 bit vào mảng byte

Nếu tôi có danh sách nhị phân (hoặc bất kỳ python nào lưu trữ kết quả của "fread"). Tôi có thể truy cập các byte riêng lẻ trong đó bằng: bộ đệm [0], bộ đệm [1], v.v.

Tôi cần thay đổi byte [8-11] để giữ kích thước tệp 32 bit mới (đọc: đã có một tập tin ở đó, tôi cần phải cập nhật nó). Trong C + + tôi sẽ chỉ nhận được một con trỏ đến vị trí và cast nó để lưu trữ các số nguyên, nhưng với python tôi đột nhiên nhận ra tôi không có ý tưởng làm thế nào để làm một cái gì đó như thế này.

Làm cách nào để cập nhật 4 byte trong bộ đệm của tôi tại một vị trí cụ thể để giữ giá trị của một số nguyên trong python?

EDIT

tôi sẽ bổ sung thêm vì tôi có thể dường như không để con số nó ra khỏi các giải pháp (mặc dù tôi có thể thấy họ đang đi đúng hướng).

Trước hết, tôi đang ở trên trăn 2.4 (và không thể nâng cấp, các máy chủ công ty lớn) - do đó dường như giới hạn các tùy chọn của tôi. Xin lỗi vì đã không đề cập đến điều đó trước đó, tôi không biết nó có rất ít tính năng hơn.

Thứ hai, hãy làm điều này cực kỳ đơn giản.

Cho phép nói rằng tôi có tệp nhị phân có tên 'myfile.binary' với nội dung năm byte '4C53535353' trong hex - điều này tương đương với biểu diễn ascii cho chữ cái "L và 4xS" một mình trong tệp.

Nếu tôi làm:

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

nội dung nên (từ câu trả lời Sven Marnach của) tổ chức một lăm-byte chuỗi không thay đổi.

Chỉ sử dụng cơ sở Python 2.4, làm cách nào tôi có thể thay đổi 4 S được giữ trong 'nội dung' thành giá trị số nguyên tùy ý? I E. cung cấp cho tôi một dòng mã có thể tạo nội dung chỉ mục byte [1-4] chứa số nguyên 32 bit 'myint' với giá trị 12345678910.

+0

bạn không thể thay đổi nội dung từ các chuỗi không thay đổi ... bạn có thể cre ăn một chuỗi mới, hoặc sử dụng một container có thể thay đổi như bytearray. – hochl

+0

Cảm ơn, tôi rất vui khi tạo chuỗi mới hoặc mảng byte nếu trường hợp đó xảy ra. Làm thế nào tôi có thể tạo một mảng byte có thể sửa đổi với cùng các contnets, và cập nhật phạm vi [1-4] của nó bằng với biểu diễn nhị phân của số nguyên của tôi? –

+0

Tôi đã mở rộng bài đăng của mình bên dưới và bao gồm ví dụ làm việc cho Python 2.4 :-) – hochl

Trả lời

8

gì bạn cần là chức năng này:

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

Nó ghi nhận tại http://docs.python.org/library/struct.html gần đầu trang.

đang

Ví dụ:

import struct 
import ctypes 

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

tương tự gửi bài:Python: How to pack different types of data into a string buffer using struct.pack_into

EDIT: Added một Python 2.4 tương thích ví dụ:

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. Tôi muốn đề nghị sử dụng 'bytearray' dựng sẵn để tạo bộ đệm có thể thay đổi thay vì' ctypes.create_string_buffer'. –

+0

** Đối với tất cả mọi người ** Tôi đã thử làm việc bằng cách đọc trang gói và các giải pháp được cung cấp. Tôi dường như mất tích rất nhiều kể từ khi tôi có python 2,4 thay vì 2,5. Tôi đã cung cấp một phiên bản rất đơn giản về vấn đề của tôi trong bản chỉnh sửa cho bài đăng của tôi ở trên - nếu bạn có thể trả lời bằng một dòng mã, tôi sẽ hoàn toàn hài lòng :) –

+1

Tôi sợ phiên bản tương thích 2.4 của bạn không thể sử dụng ' bytearray' như nó đã được giới thiệu trong 2.6. –

4

Hãy xem mô hình Struct. Bạn cần chức năng pack.

EDIT:

Mã:

import struct 

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

Output:

L╙☻ЦI 

struct.pack nên có sẵn trong python2.4.

Số của bạn "12345678910" không thể được đóng gói thành 4 byte, tôi rút ngắn một chút.

+0

* xem nhận xét về câu trả lời của hochl * –

+0

cập nhật câu trả lời –

2

Kết quả của file.read() là một chuỗi bằng Python và không thay đổi được. Tùy thuộc vào ngữ cảnh của tác vụ bạn đang cố gắng thực hiện, có các giải pháp khác nhau cho vấn đề.

Một tài khoản đang sử dụng số array module: Đọc tệp trực tiếp dưới dạng mảng số nguyên 32 bit. Bạn có thể sửa đổi mảng này và ghi nó trở lại tệp.

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

* xem nhận xét về câu trả lời của hochl * –

2

Bạn có thể cài đặt các module NumPy, mà thường được sử dụng cho máy tính khoa học.

read_data = numpy.fromfile (file = id, dtype = numpy.uint32)

Sau đó truy cập vào dữ liệu tại vị trí mong muốn và thực hiện thay đổi.

+1

* xem nhận xét về câu trả lời của hochl * –

0

Sau đây chỉ là một minh chứng cho bạn để hiểu những gì thực sự xảy ra khi bốn byte được chuyển đổi thành một số nguyên. Giả sử bạn có một số: 15213

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

Trên hệ thống ít về cuối nhỏ (ví dụ các máy x86), con số này có thể được biểu diễn bằng một bytearray chiều dài-4 như: b"\x6d\x3b\x00\x00" hoặc b"m;\x00\x00" khi bạn in nó trên màn hình, để chuyển đổi bốn byte vào một số nguyên, chúng tôi chỉ đơn giản là làm một chút về chuyển đổi cơ sở, mà trong trường hợp này, là:

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

này mang đến cho bạn kết quả: 15213

Các vấn đề liên quan