12

THIS SHOULD BE EASY! But i've been unable to find the answer to this question.

Using python, I want to read a binary file into memory, modify the first four bytes of the file, and then write the file back.

There has to be a simple way to edit four measly bytes! right?

CodingWithoutComments
  • 35,598
  • 21
  • 73
  • 86

6 Answers6

17

Why read the entire file to change four bytes at the beginning? Shouldn't this work?

with open("filename.txt", "r+b") as f:
     f.write(chr(10) + chr(20) + chr(30) + chr(40))

Even if you need to read these bytes from the file to calculate the new values, you could still do:

with open("filename.txt", "r+b") as f:
    fourbytes = [ord(b) for b in f.read(4)]
    fourbytes[0] = fourbytes[1]  # whatever, manipulate your bytes here
    f.seek(0)
    f.write("".join(chr(b) for b in fourbytes))
kindall
  • 178,883
  • 35
  • 278
  • 309
  • maybe the values of the new first 4 bytes depend on the rest of the file content? – Tomasz Elendt Jan 05 '11 at 00:46
  • Maybe this is a novice question, but how can you write to the file if you've opened it in `"r+b"` mode, which in my understanding stands for 'read' and 'binary'? – edddd Nov 11 '21 at 06:13
  • `r` means "read", `+` means "plus write," `b` means "binary". (basically "+" enables both reading and writing regardless of whether you specified "r", "w", or "a" mode.) the main difference then becomes whether the file is created if necessary ("w") and where the writes occur ("a" always writes at the end) – kindall May 09 '22 at 17:35
6
with open(filename, 'r+b') as f:
  bytes = f.read(4)
  newbytes = 'demo'
  f.seek(0)
  f.write(newbytes)
Emilio Silva
  • 1,942
  • 14
  • 17
2
C:\junk>copy con qwerty.txt
qwertyuiop
^Z
        1 file(s) copied.

C:\junk>\python27\python
Python 2.7.1 (r271:86832, Nov 27 2010, 18:30:46) [MSC v.1500 32 bit (Intel)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> f = open('qwerty.txt', 'r+b')
>>> f.write('asdf')
>>> f.close()
>>> open('qwerty.txt', 'rb').read()
'asdftyuiop\r\n'
>>>
John Machin
  • 81,303
  • 11
  • 141
  • 189
1

Simply, but memory inefficiently,

The Python 3 way:

def binaryedit(fn):
 f=open(fn,mode='rb')
 fc=f.read()
 f.close()
 return b'rawr'+fc[4:]

The Python 2 way:

def binaryedit(fn):
 f=open(fn,mode='rb')
 fc=f.read()
 f.close()
 return 'rawr'+fc[4:]

If the files are huge, you can memory map them and edit/write just the bytes that need to change. There's barely any difference until they get over a meg or so, though.

SilverbackNet
  • 2,076
  • 17
  • 29
1

This looks a lot like HW so I will not give exact code. but here is enough information

  1. You dont need to read the whole file into memory for changing the first 4 bytes
  2. Open the file in mode 'r+b'
  3. Use f.seek(0) to seek to the begining
  4. Write 4 bytes of data using f.write('ABCD')
  5. Close the file
anijhaw
  • 8,954
  • 7
  • 35
  • 36
  • Sorry, mode='a' is not portable, as the manual says: """'a' for appending (which on some Unix systems means that all writes append to the end of the file regardless of the current seek position).""" – John Machin Jan 05 '11 at 01:07
  • and now you don't need to seek :) – John Machin Jan 05 '11 at 01:18
  • yup but since I did not submit code, its okay to give a general idea? What do you think? – anijhaw Jan 05 '11 at 02:53
0

this should help. http://www.johnny-lin.com/cdat_tips/tips_fileio/bin_array.html

import Numeric as N import array

num_lon = 144 num_lat = 73 tmpfile = "tmp.bin"

fileobj = open(tmpfile, mode='rb') binvalues = array.array('f') binvalues.read(fileobj, num_lon * num_lat)

data = N.array(binvalues, typecode=N.Float)

data = N.reshape(data, (num_lat, num_lon))

fileobj.close()
madmik3
  • 6,975
  • 3
  • 38
  • 60