Python метод для хранения списка байтов в сети (big-endian) порядок байтов в файл (little-endian)
В настоящее время моя задача состоит в том, чтобы проанализировать данные tcpdump, которые включают P2P-сообщения, и у меня возникли проблемы с фрагментарными данными, которые я получаю и записываю в файл на моей машине x86. Я подозреваю, что у меня есть простая проблема с конечностью с байтами, которые я записываю в файл.
У меня есть список байтов, содержащих фрагмент P2P-видео, прочитанного и обработанного с помощью пакета python-pcapy.
bytes = [14, 254, 23, 35, 34, 67, etc... ]
Я ищу способ хранения этих байтов, которые в настоящее время хранятся в списке в моем приложении Python, чтобы файл.
В настоящее время я пишу пьесы следующим образом:
def writePiece(self, filename, pieceindex, bytes, ipsrc, ipdst, ts):
file = open(filename,"ab")
# Iterate through bytes writing them to a file if don't have piece already
if not self.piecemap[ipdst].has_key(pieceindex):
for byte in bytes:
file.write('%c' % byte)
file.flush()
self.procLog.info("Wrote (%d) bytes of piece (%d) to %s" % (len(bytes), pieceindex, filename))
# Remember we have this piece now in case duplicates arrive
self.piecemap[ipdst][pieceindex] = True
# TODO: Collect stats
file.close()
Как вы можете видеть из цикла for, я записываю байты в файл в том же порядке, что и обрабатываю их из провода (т. е. сетевой или Биг-эндианский порядок).
Достаточно сказать, что видео, которое является полезной нагрузкой частей, не воспроизводится хорошо в VLC : - D
Я думаю, что мне нужно преобразовать их в порядок байтов little-endian, но не уверен, что лучший способ подойти к этому в Python.
Обновление
Решение, которое сработало для меня (написание частей P2P, обрабатывающих эндианские проблемы соответствующим образом), было:
def writePiece(self, filename, pieceindex, bytes, ipsrc, ipdst, ts):
file = open(filename,"r+b")
if not self.piecemap[ipdst].has_key(pieceindex):
little = struct.pack('<'+'B'*len(bytes), *bytes)
# Seek to offset based on piece index
file.seek(pieceindex * self.piecesize)
file.write(little)
file.flush()
self.procLog.info("Wrote (%d) bytes of piece (%d) to %s" % (len(bytes), pieceindex, filename))
# Remember we have this piece now in case duplicates arrive
self.piecemap[ipdst][pieceindex] = True
file.close()
Ключом к решению было использование модуля Python struct в качестве подозреваемого и, в частности:
little = struct.pack('<'+'B'*len(bytes), *bytes)
Спасибо тем, кто откликнулся полезными предложениями.
3 ответа:
Можно также использовать массив .массив :
from array import array f.write(array('B', bytes))
Вместо
f.write(struct.pack('<'+'B'*len(bytes), *bytes))
Который, когда немного прибран, является
f.write(struct.pack('B' * len(bytes), *bytes)) # the < is redundant; there is NO ENDIANNESS ISSUE
Который, если len (bytes) "большой" , может быть лучше как
f.write(struct.pack('%dB' % len(bytes), *bytes))
Чтобы сэкономить себе немного работы, вы могли бы использовать
bytearray
(Python 2.6 и более поздние версии):b = [14, 254, 23, 35] f = open("file", 'ab') f.write(bytearray(b))
Это делает все преобразование ваших 0-255 значений в байты без необходимости всех циклов.
Я не могу понять, в чем заключается ваша проблема без дополнительной информации. Если данные действительно являются байтовыми, то endianness не является проблемой, как говорили другие.
(Кстати, использование
bytes
иfile
в качестве имен переменных не очень хорошо, так как они скрывают встроенные элементы одного и того же имя).
На этот вопрос можно было ответить ранее в Python File Slurp w/ endian conversion.