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 4

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.