I have a string of 1's and 0's in Python and I would like to write it to a binary file. I'm having a lot of trouble with finding a good way to do this.
Is there a standard way to do this that I'm simply missing?
If you want a binary file,
>>> import struct
>>> myFile=open('binaryFoo','wb')
>>> myStr='10010101110010101'
>>> x=int(myStr,2)
>>> x
76693
>>> struct.pack('i',x)
'\x95+\x01\x00'
>>> myFile.write(struct.pack('i',x))
>>> myFile.close()
>>> quit()
$ cat binaryFoo
�+$
Is this what you are looking for?
In [1]: int('10011001',2)
Out[1]: 153
Split your input into pieces of eight bits, then apply int(_, 2) and chr, then concatenate into a string and write this string to a file.
Something like...:
your_file.write(''.join(chr(int(your_input[8*k:8*k+8], 2)) for k in xrange(len(your_input)/8)))
There is a bitstring module now which does what you need.
from bitstring import BitArray
my_str = '001001111'
binary_file = open('file.bin', 'wb')
b = BitArray(bin=my_str)
b.tofile(binary_file)
binary_file.close()
You can test it from the shell in Linux with xxd -b file.bin
Or you can use the array module like this
$ python
Python 2.7.2+ (default, Oct 4 2011, 20:06:09)
[GCC 4.6.1] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import random,array
#This is the best way, I could think of for coming up with an binary string of 100000
>>> binStr=''.join([str(random.randrange(0,2)) for i in range(100000)])
>>> len(binStr)
100000
>>> a = array.array("c", binStr)
#c is the type of data (character)
>>> with open("binaryFoo", "ab") as f:
... a.tofile(f)
...
#raw writing to file
>>> quit()
$
BITS_IN_BYTE = 8
chars = '00111110'
bytes = bytearray(int(chars[i:i+BITS_IN_BYTE], 2)
for i in xrange(0, len(chars), BITS_IN_BYTE))
open('filename', 'wb').write(bytes)
Related
I'm trying to concatenate two strings in my function. I tried all concatenation, but those two strings just don't concatenate one after another, instead, shorter strings B(length = s) substitute the first s units of longer string A.
I read some data from input file, and store third line whose content is "00001M035NNYY1111111" into a variable called applicant:
data = open("input.txt").read().split('\n')
applicant = str(data[2])
I want to add an integer 8 at the end of applicant, so the new applicant will be "00001M035NNYY11111118". I tried applicant += str(8) and "".join((applicant, str(8))) and other concatenation methods, but all of them only give me "80001M035NNYY1111111"... Does anyone know why this happened and how am I suppose to do to get my intended result.
You probably have Windows line endings in your file: \r\n. By splitting on \n, you leave the \r, which returns to the beginning of the line. You can trim it manually:
with open("input.txt") as f:
data = [line.rstrip() for line in f]
This should work
[GCC 7.3.0] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> data = open("input.txt").read().split("\n")
>>> applicant = data[2] + str(8)
>>> print applicant
00001M035NNYY11111118
>>>
There is probably something wrong with your text file if this does not work.
Is there an easy way to print a string that contains a new line \n, aligned to the left after a certain number of characters?
Basically, what I have is something like
A = '[A]: '
B = 'this is\na string\nwith a new line'
print('{:<10} {}'format(A, B))
The problem is that with the new line, the next lines do not start at the 10th column:
[A]: this is
a string
with a new line
I would like something like
[A]: this is
a string
with a new line
I could maybe split B, but I was wondering if there was an optial way of doing this
An easy way to achieve this is replacing a new line with a new line and 11 (11 because of the 10 in {:<10} but you add an additional space in your format) spaces:
B2 = B.replace('\n','\n ')
print('{:<10} {}'.format(A, B2))
Or perhaps more elegantly:
B2 = B.replace('\n','\n'+11*' ')
print('{:<10} {}'.format(A, B2))
Running this in python3:
$ python3
Python 3.5.2 (default, Nov 17 2016, 17:05:23)
[GCC 5.4.0 20160609] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> A = '[A]: '
>>> B = 'this is\na string\nwith a new line'
>>> B2 = B.replace('\n','\n ')
>>> print('{:<10} {}'.format(A, B2))
[A]: this is
a string
with a new line
I want to iterate over lines cStringIO object, however it does not seem to work with foreach loop. To be more precise the behavior is as if the collection was empty. What am I doing wrong?
example:
Python 2.7.12 (default, Aug 29 2016, 16:51:45)
[GCC 4.4.7 20120313 (Red Hat 4.4.7-3)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import cStringIO
>>> s = cStringIO.StringIO()
>>> import os
>>> s.write("Hello" + os.linesep + "World" + os.linesep)
>>> s.getvalue()
'Hello\nWorld\n'
>>> for line in s :
... print line
...
>>>
Thank you.
cStringIO.StringIO returns either cStringIO.InputType object i.e input stream if provided a string else or cStringIO.OutputType object i.e output stream.
In [13]: sio = cStringIO.StringIO()
In [14]: sio??
Type: StringO
String form: <cStringIO.StringO object at 0x7f63d418f538>
Docstring: Simple type for output to strings.
In [15]: isinstance(sio, cStringIO.OutputType)
Out[15]: True
In [16]: sio = cStringIO.StringIO("dsaknml")
In [17]: sio??
Type: StringI
String form: <cStringIO.StringI object at 0x7f63d4218580>
Docstring: Simple type for treating strings as input file streams
In [18]: isinstance(sio, cStringIO.InputType)
Out[18]: True
So you can either do read operations or write operations but not both. a simple solution to do read operations on a cStringIO.OutputType object is by converting it into the value by getvalue() method.
If you try do both operations then either of them gets ignored silently.
cStringIO.OutputType.getvalue(c_string_io_object)
Try using the string split method:
for line in s.getvalue().split('\n'): print line
...
Hello
World
Or as suggested, if you are always splitting on a new line:
for line in s.getvalue().splitlines(): print line
You can read the contents from an open file handle after writing, but you first have to use the seek(0) method to move the pointer back to the start. This will work for either cStringIO or a real file:
import cStringIO
s = cStringIO.StringIO()
s.write("Hello\nWorld\n") # Python automatically converts '\n' as needed
s.getvalue()
# 'Hello\nWorld\n'
s.seek(0) # move pointer to start of file
for line in s :
print line.strip()
# Hello
# World
I made a decryption .py file for fun but while decrypting, the text is displayed vertically. My current code is:
while depthTracker >= 0:
depthTracker -= 1
multiplier = 32 ** depthTracker
letter = userIn
letter = letter // multiplier
userIn -= letter * multiplier
letterPrint(letter)
In this code, each letter is decrypted one at a time and is displayed with my def function def letterPrint(nb): which prints the correct letter according to a number.
In letterPrint , where you are printing, do
print('whaterver you want to print',end = ' ')
If you leave a dangling comma at the end of your print command in letterPrint, the system routine will not start a new line. I can't comment on your actual code, since you failed to provide it. However, it might look something like this:
print letter,
Note that trailing comma.
What version of python?
If it's 2.7 I think you can change the print statement in letterPrint to the following:
print str,
If it's 3.0 I think you can do this equivalently:
print(str, end=" ")
Is this the behaviour you want?
Python 2.7 (r27:82525, Jul 4 2010, 07:43:08) [MSC v.1500 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
i = 1
while i < 5:
print "hi",
i = i + 1
> hi hi hi hi
I am trying to search and replace some of the text (eg 'Smith, John') in this pdf form file (header.fdf, I presumed this is treated as binary file):
'%FDF-1.2\n%\xe2\xe3\xcf\xd3\n1 0 obj\n<</FDF<</Fields[<</V(M)/T(PatientSexLabel)>><</V(24-09-1956 53)/T(PatientDateOfBirth)>><</V(Fisher)/T(PatientLastNameLabel)>><</V(CNSL)/T(PatientConsultant)>><</V(28-01-2010 18:13)/T(PatientAdmission)>><</V(134 Field Street\\rBlackburn BB1 1BB)/T(PatientAddressLabel)>><</V(Smith, John)/T(PatientName)>><</V(24-09-1956)/T(PatientDobLabel)>><</V(0123456)/T(PatientRxr)>><</V(01234567891011)/T(PatientNhsLabel)>><</V(John)/T(PatientFirstNameLabel)>><</V(0123456)/T(PatientRxrLabel)>>]>>>>\nendobj\ntrailer\n<</Root 1 0 R>>\n%%EOF\n'
After
f=open("header.fdf","rb")
s=f.read()
f.close()
s=s.replace(b'PatientName',name)
the following error occurs:
Traceback (most recent call last):
File "/home/aj/Inkscape/Med/GAD/gad.py", line 56, in <module>
s=s.replace(b'PatientName',name)
TypeError: expected an object with the buffer interface
How best to do this?
f=open("header.fdf","rb")
s=str(f.read())
f.close()
s=s.replace(b'PatientName',name)
or
f=open("header.fdf","rb")
s=f.read()
f.close()
s=s.replace(b'PatientName',bytes(name))
probably the latter, as I don't think you are going to be able to use unicode names with this type of substitution anyway
You must be using Python 3.X. You didn't define 'name' in your example, but it is the problem. Likely you defined it as a Unicode string:
name = 'blah'
It needs to be a bytes object too:
name = b'blah'
This works:
Python 3.1.2 (r312:79149, Mar 21 2010, 00:41:52) [MSC v.1500 32 bit (Intel)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> f = open('file.txt','rb')
>>> s = f.read()
>>> f.close()
>>> s
b'Test File\r\n'
>>> name = b'Replacement'
>>> s=s.replace(b'File',name)
>>> s
b'Test Replacement\r\n'
In a bytes object, the arguments to replace must both be bytes objects.