Преобразование двоичных данных в текст, безопасный для Интернета, и обратно - Python - PullRequest
0 голосов
/ 23 октября 2011

Я хочу преобразовать двоичный файл (такой как jpg, mp3 и т. Д.) В текст, безопасный для Интернета, а затем обратно в двоичные данные. Я исследовал несколько модулей, и я думаю, что я действительно близок, но я продолжаю получать повреждение данных.

После просмотра документации для binascii я придумал это:

from binascii import *
raw_bytes = open('test.jpg','rb').read()
text = b2a_qp(raw_bytes,quotetabs=True,header=False)
bytesback = a2b_qp(text,header=False)
f = open('converted.jpg','wb')
f.write(bytesback)
f.close()

Когда я пытаюсь открыть converted.jpg, я получаю повреждение данных: - /

Я также пытался использовать b2a_base64 с 57-длинными блоками двоичных данных. Я взял каждый блок, преобразовал его в строку, соединил их все вместе, а затем преобразовал обратно в a2b_base64 и снова получил повреждение.

Кто-нибудь может помочь? Я не очень разбираюсь во всех тонкостях байтов и форматов файлов. Я использую Python на Windows, если это имеет значение с \r\n stuff

Ответы [ 4 ]

1 голос
/ 24 октября 2011

Ссылка на документацию для Python 3.0.1. Нет веской причины использовать Python 3.0. Вы должны использовать 3.2 или 2.7. Что именно вы используете?

Предложение: (1) изменить bytes на raw_bytes, чтобы избежать путаницы со встроенной проверкой bytes (2) для raw_bytes == bytes_back в вашем тестовом скрипте (3) во время теста должен работать с кавычками для печати, это очень неэффективно для двоичных данных; используйте взамен base64.

Обновление: кодировка Base64 создает 4 выходных байта на каждые 3 входных байта. Ваш код base64 не работает с 56-байтовыми блоками, потому что 56 не является целым кратным 3; каждый чанк дополняется кратным 3. Затем вы присоединяете чанки и пытаетесь декодировать, что гарантированно не сработает.

Ваш цикл будет намного лучше записан как:

output_string = ''.join(
    b2a_base64(raw_bytes[i:i+57]) for i in xrange(0, xrange(len(raw_bytes), 57)
    )

В любом случае, чанкинг довольно медленный и бессмысленный; просто сделай b2a_base64(raw_bytes)

1 голос
/ 24 октября 2011

Ваш код выглядит довольно сложным. Попробуйте это:

#!/usr/bin/env python

from binascii import *
raw_bytes = open('28.jpg','rb').read()
i = 0
str_one = b2a_base64(raw_bytes) # 1
str_list = b2a_base64(raw_bytes).split("\n") #2

bytesBackAll = a2b_base64(''.join(str_list)) #2
print bytesBackAll == raw_bytes #True #2

bytesBackAll = a2b_base64(str_one) #1
print bytesBackAll == raw_bytes #True #1

Линии, отмеченные #1 и #2, представляют альтернативы друг другу. #1 мне кажется наиболее простым - просто сделайте его одной строкой, обработайте его и конвертируйте обратно.

1 голос
/ 23 октября 2011

Вы должны использовать кодировку base64 вместо цитируемой для печати. Используйте b2a_base64() и a2b_base64().

Котируемая для печати гораздо больше для двоичных данных, таких как изображения. В этой кодировке каждый двоичный (не буквенно-цифровой символ) код изменяется на =HEX. Он может использоваться для текстов, которые состоят в основном из буквенно-цифровых символов, таких как темы электронной почты.

Base64 намного лучше для двоичных данных. Требуется 6 битов первого байта, затем последние 2 бита 1-го байта и 4 байта от 2-го байта. и т. д. Его можно узнать по = в конце закодированного текста (иногда используется другой символ).

В качестве примера я взял .jpeg из 271 700 байт. В qp это 627 857 байт, в то время как в base64 это 362 269 байт. Размер qp зависит от типа данных: текст, который состоит только из букв, не изменяется. Размер base64 orig_size * 8 / 6.

0 голосов
/ 24 октября 2011

@ Ответ PMC скопирован с вопроса:

Вот что работает:

from binascii import *
raw_bytes = open('28.jpg','rb').read()
str_list = []
i = 0
while i < len(raw_bytes):
    byteSegment = raw_bytes[i:i+57]
    str_list.append(b2a_base64(byteSegment))
    i += 57
bytesBackAll = a2b_base64(''.join(str_list))
print bytesBackAll == raw_bytes #True

Спасибо за помощь, ребята.Я не уверен, почему это не с [0:56] вместо [0:57], но я оставлю это в качестве упражнения для читателя: P

...