ReadInt (), ReadByte (), ReadString () и т. Д. В Python? - PullRequest
4 голосов
/ 14 января 2009

Функции ReadInt (), ReadByte () и ReadString () (если назвать несколько) существуют на других языках для чтения ввода из потоков. Я пытаюсь читать из сокета, и я хочу использовать функции, подобные этим. Они спрятаны в Python где-то по-другому или кто-то создал библиотеку для этого?

Кроме того, существуют аналоги типа данных ().

Ответы [ 4 ]

10 голосов
/ 02 декабря 2010

Python использует для чтения двоичных данных struct.unpack. Я очень привык к BinaryReader и BinaryWriter в C #, поэтому я сделал это:

from struct import *

class BinaryStream:
    def __init__(self, base_stream):
        self.base_stream = base_stream

    def readByte(self):
        return self.base_stream.read(1)

    def readBytes(self, length):
        return self.base_stream.read(length)

    def readChar(self):
        return self.unpack('b')

    def readUChar(self):
        return self.unpack('B')

    def readBool(self):
        return self.unpack('?')

    def readInt16(self):
        return self.unpack('h', 2)

    def readUInt16(self):
        return self.unpack('H', 2)

    def readInt32(self):
        return self.unpack('i', 4)

    def readUInt32(self):
        return self.unpack('I', 4)

    def readInt64(self):
        return self.unpack('q', 8)

    def readUInt64(self):
        return self.unpack('Q', 8)

    def readFloat(self):
        return self.unpack('f', 4)

    def readDouble(self):
        return self.unpack('d', 8)

    def readString(self):
        length = self.readUInt16()
        return self.unpack(str(length) + 's', length)

    def writeBytes(self, value):
        self.base_stream.write(value)

    def writeChar(self, value):
        self.pack('c', value)

    def writeUChar(self, value):
        self.pack('C', value)

    def writeBool(self, value):
        self.pack('?', value)

    def writeInt16(self, value):
        self.pack('h', value)

    def writeUInt16(self, value):
        self.pack('H', value)

    def writeInt32(self, value):
        self.pack('i', value)

    def writeUInt32(self, value):
        self.pack('I', value)

    def writeInt64(self, value):
        self.pack('q', value)

    def writeUInt64(self, value):
        self.pack('Q', value)

    def writeFloat(self, value):
        self.pack('f', value)

    def writeDouble(self, value):
        self.pack('d', value)

    def writeString(self, value):
        length = len(value)
        self.writeUInt16(length)
        self.pack(str(length) + 's', value)

    def pack(self, fmt, data):
        return self.writeBytes(pack(fmt, data))

    def unpack(self, fmt, length = 1):
        return unpack(fmt, self.readBytes(length))[0]

Получив поток, вы помещаете его в конструктор BinaryStream и получаете BinaryStream :)

Пример:

from binary import BinaryStream

f = open("Users", "rb")
stream = BinaryStream(f)
users_count = stream.readUInt64()
for i in range(users_count):
    username = stream.readString()
    password = stream.readString()
8 голосов
/ 14 января 2009

Я думаю, struct.unpack_from - это то, что вы ищете.

1 голос
/ 19 марта 2014

Я использовал код Zippoxer, и он работает практически для всего, спасибо.

Однако у меня были некоторые проблемы с readString (). В документе C # было указано, что длина кодируется в 7 байтов. Таким образом я использовал readUChar вместо readUInt16:

def readString(self):
    length = self.readUChar()
    return self.unpack(str(length) + 's', length)

и теперь работает. Может, это специфично для моей проблемы? Но это может кому-то помочь ...

0 голосов
/ 14 января 2009

Обратите внимание, что в Python нет readByte, readInt и readString, потому что он не работает напрямую со всеми этими причудливыми типами данных. Файлы содержат строки, которые вы можете конвертировать.

Python <= 2.6 имеет String, и это то, что вы получаете из ваших входных потоков - строк. Простой socket.read() обеспечивает этот ввод. Вы можете использовать struct для преобразования потока в последовательность целых чисел. Важным является то, что преобразования пакета и распаковки могут быть байтовыми, словесными, длинными или как угодно, но результат Python - целые числа.

Таким образом, ваши входные данные могут быть байтами, но Python представляет это как строку, большая часть которой непечатна. Ваше желание может быть массивом отдельных значений, каждое от 0 до 255, которые являются числовыми версиями этих байтов. Python представляет их как целые числа.

Python >= 3.0 имеет байтовые массивы, которые можно использовать для непосредственной обработки байтов. Вы можете преобразовать их в строки или целые числа (которые включают байты и длинные значения) или что-либо еще.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...