İkili dosyayı ASCII'ye ve tersini dönüştürme


83

Bir dizeyi alıp ikiliye dönüştürmek için bu kodu kullanma:

bin(reduce(lambda x, y: 256*x+y, (ord(c) for c in 'hello'), 0))

bu çıktılar:

0b110100001100101011011000110110001101111

Ki bu siteye koyarsam (sağdaki site) mesajımı hellogeri alırım . Hangi yöntemi kullandığını merak ediyorum. İkili diziyi 8'lere ayırabileceğimi ve ardından onu karşılık gelen değerle bin(ord(character))veya başka bir şekilde eşleştirebileceğimi biliyorum . Gerçekten daha basit bir şey arıyorum.


1
Öyleyse sorunuz, "kodumun tersini yapmanın bariz olandan daha kısa ve öz bir yolu var mı?" Mı?
üçlü

1
related: b2a_binextension Cython'da , "01"bir ara Python tamsayı oluşturmadan doğrudan bytestrings'den ikili dizeler ( ) oluşturmaya izin verir .
jfs

Yanıtlar:


160

[ -~]Python 2'deki aralıktaki ASCII karakterleri için :

>>> import binascii
>>> bin(int(binascii.hexlify('hello'), 16))
'0b110100001100101011011000110110001101111'

Geri viteste:

>>> n = int('0b110100001100101011011000110110001101111', 2)
>>> binascii.unhexlify('%x' % n)
'hello'

Python 3.2+ sürümünde:

>>> bin(int.from_bytes('hello'.encode(), 'big'))
'0b110100001100101011011000110110001101111'

Geri viteste:

>>> n = int('0b110100001100101011011000110110001101111', 2)
>>> n.to_bytes((n.bit_length() + 7) // 8, 'big').decode()
'hello'

Python 3'teki tüm Unicode karakterlerini desteklemek için:

def text_to_bits(text, encoding='utf-8', errors='surrogatepass'):
    bits = bin(int.from_bytes(text.encode(encoding, errors), 'big'))[2:]
    return bits.zfill(8 * ((len(bits) + 7) // 8))

def text_from_bits(bits, encoding='utf-8', errors='surrogatepass'):
    n = int(bits, 2)
    return n.to_bytes((n.bit_length() + 7) // 8, 'big').decode(encoding, errors) or '\0'

İşte tek kaynaklı Python 2/3 uyumlu sürüm:

import binascii

def text_to_bits(text, encoding='utf-8', errors='surrogatepass'):
    bits = bin(int(binascii.hexlify(text.encode(encoding, errors)), 16))[2:]
    return bits.zfill(8 * ((len(bits) + 7) // 8))

def text_from_bits(bits, encoding='utf-8', errors='surrogatepass'):
    n = int(bits, 2)
    return int2bytes(n).decode(encoding, errors)

def int2bytes(i):
    hex_string = '%x' % i
    n = len(hex_string)
    return binascii.unhexlify(hex_string.zfill(n + (n & 1)))

Misal

>>> text_to_bits('hello')
'0110100001100101011011000110110001101111'
>>> text_from_bits('110100001100101011011000110110001101111') == u'hello'
True

3
@JFSebastian bu yöntemi python güncel sürümü ile denedim ve çalışmıyor gibi görünüyor. <br/> TypeError: 'str' arabellek arayüzünü desteklemiyor <br/> Cevabınızı günceller misiniz
hamza

3
@hamza: Python 2'de çalışır. Python 3'te önce str'yi bayta dönüştürmelisiniz örn.your_string.encode('ascii', 'strict')
jfs

1
@JFSebasitian: teşekkürler, ancak tam tersini denediğimde, unhexlify işlevi bir hata mesajı veriyor: binascii.Error: Tek uzunlukta dize.
hamza

3
@hamza: '0'hex-string'in uzunluğu çift değilse başına ekleyin . Orijinal dizedeki ilk karakter 16'dan küçük ascii koduna sahipse, örneğin, '\n'veya '\t'. Ascii harfleri için tek uzunluk asla olmaz [ -~].
jfs

25

Yalnızca yerleşikpython

İşte basit dizeler için saf bir python yöntemi, gelecek nesil için burada bırakılmıştır.

def string2bits(s=''):
    return [bin(ord(x))[2:].zfill(8) for x in s]

def bits2string(b=None):
    return ''.join([chr(int(x, 2)) for x in b])

s = 'Hello, World!'
b = string2bits(s)
s2 = bits2string(b)

print 'String:'
print s

print '\nList of Bits:'
for x in b:
    print x

print '\nString:'
print s2

String:
Hello, World!

List of Bits:
01001000
01100101
01101100
01101100
01101111
00101100
00100000
01010111
01101111
01110010
01101100
01100100
00100001

String:
Hello, World!

2
chr (int ()) aradığım şeydi!
JqueryToAddNumbers

Ben de tam olarak aradığım şey !!
Joachim

10

Bunu karakter karakter dışında nasıl yapabileceğinizi düşündüğünüzden emin değilim - doğası gereği karakter karakter bir işlemdir. Bunu sizin için yapacak bir kod kesinlikle vardır, ancak bunu karakter karakter yapmaktan daha "basit" bir yol yoktur.

İlk olarak, 0bbit dizisini karakterlere bölmeyi kolaylaştırmak için öneki çıkarmanız ve dizeyi sol sıfıra doldurmanız gerekir, böylece uzunluğu 8'e bölünebilir:

bitstring = bitstring[2:]
bitstring = -len(bitstring) % 8 * '0' + bitstring

Ardından dizeyi sekiz ikili basamaktan oluşan bloklara böler, bunları ASCII karakterlerine dönüştürür ve bir dizede birleştirirsiniz:

string_blocks = (bitstring[i:i+8] for i in range(0, len(bitstring), 8))
string = ''.join(chr(int(char, 2)) for char in string_blocks)

Bunu gerçekten bir sayı olarak ele almak istiyorsanız, sağdan sola yerine soldan sağa gitmek istiyorsanız, en soldaki karakterin en fazla yedi basamak uzunluğunda olacağı gerçeğini hesaba katmalısınız.


2

Görevini çözmenin yolu bu:

str = "0b110100001100101011011000110110001101111"
str = "0" + str[2:]
message = ""
while str != "":
    i = chr(int(str[:8], 2))
    message = message + i
    str = str[8:]
print message

Str = "0" + str [2:] 'ye neden' 0 'ekliyorsunuz? Başladığı için buradan kaldırmak için 0b gereklidir.
bimlesh sharma

2

Herhangi bir dosyayı içe aktarmak istemiyorsanız, bunu kullanabilirsiniz:

with open("Test1.txt", "r") as File1:
St = (' '.join(format(ord(x), 'b') for x in File1.read()))
StrList = St.split(" ")

bir metin dosyasını ikiliye dönüştürmek için.

ve bunu tekrar dizeye dönüştürmek için kullanabilirsiniz:

StrOrgList = StrOrgMsg.split(" ")


for StrValue in StrOrgList:
    if(StrValue != ""):
        StrMsg += chr(int(str(StrValue),2))
print(StrMsg)

umarım yardımcı olur, bunu TCP üzerinden göndermek için bazı özel şifreleme ile kullandım.


1

Bunu yapacak kodu mu arıyorsunuz yoksa algoritmayı mı anlıyorsunuz?

Bu ihtiyacın olanı yapıyor mu? Özellikle a2b_uuve b2a_uu? İstediklerinizin bunlar olmaması ihtimaline karşı, orada çok sayıda başka seçenek var.

(NOT: Bir Python adamı değil ama bu açık bir cevap gibi görünüyordu)


Bir süredir araştırıyorum, binascii benim için çalışmıyor ve çoğunlukla kodu arıyor, eğer görebilirsem anlayabilirim. EDIT'e rağmen teşekkürler: "h" için binascii a2b_uu kullanarak ascii'yi ikiliye dönüştürürken \ x00 \ x00 \ x00 \ x00 \ x00 \ x00 \ x00 \ x00 bu ihtiyacım olan şey değil, "merhaba" ve gerçek 1'ler ve 0'lara ihtiyacım var
ascii'ye benzeyen

@Jaxidian, benim amaçlarıma oldukça yardımcı oldu. Birisi bazı verileri bir dizede sakladı ve bende var. Dolgunun 64binary b / c olduğundan oldukça eminim. Bunu başarılı bir şekilde kullanabilirim b2a_base64, ancak sonuç gerçekten de en iyi ihtimalle kafa karıştırıcı. Oradan boolleans / tamsayıların (0,1) listesini nasıl alabilirim?
Ufos

0

İkiliyi eşdeğer karakterine dönüştürün.

k=7
dec=0
new=[]
item=[x for x in input("Enter 8bit binary number with , seprator").split(",")]
for i in item:
    for j in i:
        if(j=="1"):
            dec=2**k+dec
            k=k-1
        else:
            k=k-1
    new.append(dec)
    dec=0
    k=7
print(new)
for i in new:
    print(chr(i),end="")

-1

Bu, JF Sebastian'ın şık bir versiyonudur. JF Sebastian küçük parçalar için teşekkürler.

import binascii, sys
def goodbye():
    sys.exit("\n"+"*"*43+"\n\nGood Bye! Come use again!\n\n"+"*"*43+"")
while __name__=='__main__':
    print "[A]scii to Binary, [B]inary to Ascii, or [E]xit:"
    var1=raw_input('>>> ')
    if var1=='a':
        string=raw_input('String to convert:\n>>> ')
        convert=bin(int(binascii.hexlify(string), 16))
        i=2
        truebin=[]
        while i!=len(convert):
            truebin.append(convert[i])
            i=i+1
        convert=''.join(truebin)
        print '\n'+'*'*84+'\n\n'+convert+'\n\n'+'*'*84+'\n'
    if var1=='b':
        binary=raw_input('Binary to convert:\n>>> ')
        n = int(binary, 2)
        done=binascii.unhexlify('%x' % n)
        print '\n'+'*'*84+'\n\n'+done+'\n\n'+'*'*84+'\n'
    if var1=='e':
        aus=raw_input('Are you sure? (y/n)\n>>> ')
        if aus=='y':
            goodbye()
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.