2016-03-02 15 views
1

我從mp3數據中提取jpeg類型位實際上它將是專輯藝術。 我想過使用叫做mutagen的庫,但我想嘗試一些練習目的的位。python文件與二進制數據的I/O

import os 
import sys 
import re 

f = open(sys.argv[1], "rb") 
#sys.argv[1] gets mp3 file name ex) test1.mp3 

saver = "" 
for value in f: 
    for i in value: 
     hexval = hex(ord(i))[2:] 
     if (ord(i) == 0): 
      saver += "00" #to match with hex form 
     else: 
      saver += hexval 


header = "ffd8" 
tail = "ffd9" 

這部分代碼是讓MP3的比特形式,然後將其轉換爲十六進制 並找到該程序可以「FFD8」,並以「ffd9」

frontmatch = re.search(header,saver) 
endmatch = re.search(tail, saver) 
startIndex = frontmatch.start() 
endIndex = endmatch.end() 

jpgcontents = saver[startIndex:endIndex] 
scale = 16 # equals to hexadecimal 
numbits = len(jpgcontents) * 4 #log2(scale) 
bitcontents = bin(int(jpgcontents, scale))[2:].zfill(numbits) 

結束JPEG拖車在這裏,我得到了頭部和尾部之間的位,並將其轉換爲 二進制形式。這應該是mp3文件的jpg部分。

txtfile = open(sys.argv[1] + "_tr.jpg", "w") 
txtfile.write(bitcontents) 

我把bin寫入新文件,寫入類型爲jpg。 抱歉我錯誤的命名爲txtfile。

但這些代碼給了這是

Error interpreting JPEG image file 
(Not a JPEG file: starts with 0x31 0x31) 

我不知道我提取的位是否是錯誤或寫入文件 步驟是錯誤的錯誤。或者代碼中可能存在其他問題。

我正在使用Python 2.6的Linux版本。 只是把str類型的bin數據寫成JPG格式有什麼不對嗎?

+0

哪一行導致異常/錯誤? –

+0

其實代碼本身不會給出錯誤。但是,當我打開生成的jpg文件,然後我得到錯誤消息,不是JPEG文件:以0x31 0x31開頭,所以我無法成功打開jpg文件 – jooShin

回答

3

你正在創建ASCII零和一,即\x30\x31的字符串,但JPEG文件需要適當的二進制數據。因此,如果您的文件應具有(例如)\xd8的單個字節,您可以使用這八個字節:11011000\x31\x31\x30\x31\x31\x30\x30\x30

你不需要做所有那些混亂的轉換東西。您可以直接搜索所需的字節模式,使用\x十六進制轉義序列編寫它們。而且你甚至不需要正則表達式:簡單的字符串.index.find方法可以輕鬆快速地完成此操作。

with open(fname, 'rb') as f: 
    data = f.read() 

header = "\xff\xd8" 
tail = "\xff\xd9" 

try: 
    start = data.index(header) 
    end = data.index(tail, start) + 2 
except ValueError: 
    print "Can't find JPEG data!" 
    exit() 

print 'Start: %d End: %d Size: %d' % (start, end, end - start) 

with open(fname + "_tr.jpg", 'wb') as f: 
    f.write(data[start:end]) 

(測試的Python 2.6.6)

然而,提取嵌入JPEG數據等,這是不萬無一失的,因爲它有可能是在MP3聲音數據存在的那些的頭部和尾部的字節序列。


FWIW,一個簡單的翻譯二進制數據爲十六進制字符串和背部的方法是使用hexlify從binascii模塊unhexlify。

下面是一些做這些轉換的例子,包括和不包含binascii函數。

from binascii import hexlify, unhexlify 

#Create a string of all possible byte values 
allbytes = ''.join([chr(i) for i in xrange(256)]) 
print 'allbytes' 
print repr(allbytes) 

print '\nhex list' 
print [hex(ord(v))[2:].zfill(2) for v in allbytes] 
hexstr = hexlify(allbytes) 

print '\nhex string' 
print hexstr 
newbytes = ''.join([chr(int(hexstr[i:i+2], 16)) for i in xrange(0, len(hexstr), 2)]) 

print '\nNew bytes' 
print repr(newbytes) 

print '\nUsing unhexlify' 
print repr(unhexlify(hexstr))  

輸出

allbytes 
'\x00\x01\x02\x03\x04\x05\x06\x07\x08\t\n\x0b\x0c\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f !"#$%&\'()*+,-./:;<=>[email protected][\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\x7f\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff' 

hex list 
['00', '01', '02', '03', '04', '05', '06', '07', '08', '09', '0a', '0b', '0c', '0d', '0e', '0f', '10', '11', '12', '13', '14', '15', '16', '17', '18', '19', '1a', '1b', '1c', '1d', '1e', '1f', '20', '21', '22', '23', '24', '25', '26', '27', '28', '29', '2a', '2b', '2c', '2d', '2e', '2f', '30', '31', '32', '33', '34', '35', '36', '37', '38', '39', '3a', '3b', '3c', '3d', '3e', '3f', '40', '41', '42', '43', '44', '45', '46', '47', '48', '49', '4a', '4b', '4c', '4d', '4e', '4f', '50', '51', '52', '53', '54', '55', '56', '57', '58', '59', '5a', '5b', '5c', '5d', '5e', '5f', '60', '61', '62', '63', '64', '65', '66', '67', '68', '69', '6a', '6b', '6c', '6d', '6e', '6f', '70', '71', '72', '73', '74', '75', '76', '77', '78', '79', '7a', '7b', '7c', '7d', '7e', '7f', '80', '81', '82', '83', '84', '85', '86', '87', '88', '89', '8a', '8b', '8c', '8d', '8e', '8f', '90', '91', '92', '93', '94', '95', '96', '97', '98', '99', '9a', '9b', '9c', '9d', '9e', '9f', 'a0', 'a1', 'a2', 'a3', 'a4', 'a5', 'a6', 'a7', 'a8', 'a9', 'aa', 'ab', 'ac', 'ad', 'ae', 'af', 'b0', 'b1', 'b2', 'b3', 'b4', 'b5', 'b6', 'b7', 'b8', 'b9', 'ba', 'bb', 'bc', 'bd', 'be', 'bf', 'c0', 'c1', 'c2', 'c3', 'c4', 'c5', 'c6', 'c7', 'c8', 'c9', 'ca', 'cb', 'cc', 'cd', 'ce', 'cf', 'd0', 'd1', 'd2', 'd3', 'd4', 'd5', 'd6', 'd7', 'd8', 'd9', 'da', 'db', 'dc', 'dd', 'de', 'df', 'e0', 'e1', 'e2', 'e3', 'e4', 'e5', 'e6', 'e7', 'e8', 'e9', 'ea', 'eb', 'ec', 'ed', 'ee', 'ef', 'f0', 'f1', 'f2', 'f3', 'f4', 'f5', 'f6', 'f7', 'f8', 'f9', 'fa', 'fb', 'fc', 'fd', 'fe', 'ff'] 

hex string 
000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff 

New bytes 
'\x00\x01\x02\x03\x04\x05\x06\x07\x08\t\n\x0b\x0c\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f !"#$%&\'()*+,-./:;<=>[email protected][\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\x7f\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff' 

Using unhexlify 
'\x00\x01\x02\x03\x04\x05\x06\x07\x08\t\n\x0b\x0c\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f !"#$%&\'()*+,-./:;<=>[email protected][\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\x7f\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff' 

注意,該代碼需要一些修改,在Python 3的運行(除了轉換print語句print函數調用),因爲普通的Python 3個字符串是Unicode字符串,不是字節串。

0

你需要寫出來二進制

嘗試:

txtfile = open(sys.argv[1] + "_tr.jpg", "wb") 
+0

謝謝我會嘗試。但我不知道爲什麼錯誤給我的文件以0x31開頭。這個十六進制值來自哪裏? – jooShin

+0

如果您在文本編輯器中打開jpg,您很可能會看到十六進制字符串的字符串表示形式。由於使用只寫打開文件的默認行爲是打印一個字符串。 –

+0

因此,如果我使用「wb」類型並將它們設置爲二進制類型,它是否可以解決問題?或者你的意思是在文本編輯器中打開jpg本身有問題? – jooShin

0

Oups,你沒有做你期望的。 bin會生成一個字符串,其中包含二進制形式的值。讓我們來看看你有什麼,如果在輸入文件中的內容是:

  • saver是十六進制字符以文本形式類似「313233414243」的「132ABC」的初始字符串的字符串
  • jpgcontents有相同的格式,並以「FFD8」開始,以「ffd9」
  • 你再申請妙方bin(int(jpgcontents, scale))[2:].zfill(numbits)
    • 的六字符串轉換爲長整型結束
    • 轉換爲二進制表示形式的字符串長整型 - 這部分將轉換六的「FF」整數255,並且如果需要的字符串「0b11111111」
  • 除去第一字符「0b」時,並填寫緩衝區的末尾在結束

bitcontents然後是一個以「11111111 ....」開頭的字符串。只是擴展名爲.txt重命名文件,並用文本編輯器打開它,你會發現它是隻包含ASCII字符 0和1

由於頭是「FFD8」的文件將一個大文件從10「1」開始。所以它以0x31 0x31開始的錯誤,因爲0x31是ascii碼「1」。

你需要的是將六進制字符串jpgcontents轉換成二進制字節數組。

fileimage = ''.join([ jpgcontent[i:i+2] for i in range(0, len(jpgcontent), 2] 

然後,您可以安全地fileimage緩衝區拷貝到一個二進制文件:

file = open(sys.argv[1] + "_tr.jpg", "wb") 
file.write(fileimage) 
0

最簡單的方法是使用binascii模塊:https://docs.python.org/2/library/binascii.html

import binascii 

# code in ascii format contained in a list 
code = ['00', '01', '02', '03', '04', '05', '06', '07', '08', '09'] 

bfile = open('bfile.bin', 'w') 

for c in code: 
    # convert the ascii to binary and write it to the file 
    bfile.write(binascii.unhexlify(c)) 

bfile.close()