Отправка файлов различных типов через tcp-сокет в python3 дает UnicodeDecodeError - PullRequest
0 голосов
/ 29 марта 2019

Написание небольшого приложения, которое позволяет мне обмениваться файлами по локальной сети дома с минимальной головной болью, насколько это возможно, , поэтому я хочу поддерживать все расширения файлов.

При отправке текстафайл Я использую функции .encode () и .decode (), и он работает просто отлично, но при попытке отправить что-то другое (видео, скажем) возвращает следующее сообщение об ошибке:

return codecs.charmap_decode(input,self.errors,decoding_table)[0]
UnicodeDecodeError: 'charmap' codec can't decode byte 0x81 in position 47: character maps to <undefined>

Есть лиспособ отправить файл как есть?без необходимости кодировать это?упомянув, что я попытался отправить файл без .encode (), и он возвращает ту же самую ошибку.

Код:

def sendfile(file, client):
    try:
        fd = open(file, 'r')
    except:
        _media_error('Can not open specific file for sending')
        return 0

    resp = client.recv(128).decode()

    # other side is ready, give them the info
    if resp == '[ack]':
        buf = fd.read(_readsize)
        while buf:
            #client.send(buf.encode())
            client.send(buf)
            buf = fd.read(_readsize)
        fd.close()
        client.send('[done]'.encode())
        return 1
    else:
        fd.close()
        return 0

def recvfile(file, client):
    try:
        fd = open(file, 'w+')
    except:
        _media_error('Can not open specific file for receiving')
        return 0

    # ready give me the info
    client.send('[ack]'.encode())
    #buf = client.recv(_readsize).decode()
    buf = client.recv(_readsize)
    while buf:
        if buf != '[done]':
            fd.write(buf)
            buf = client.recv(_readsize)#.decode()
        else:
            fd.close()
            return 1
    return 0

(Не обращайте внимания на грязные результаты, я исправлю их позже)

1 Ответ

1 голос
/ 29 марта 2019

Поскольку вы отправляете байты по сети, проще всего работать исключительно с байтами.

Откройте ваши файлы в двоичном режиме и не кодируйте и не декодируйте данные файла. Вам все равно нужно будет закодировать ваши сообщения ack / done.

def sendfile(file, client):
    try:
        fd = open(file, 'rb')
    except:
        _media_error('Can not open specific file for sending')
        return 0

    resp = client.recv(128)

    # other side is ready, give them the info
    if resp == '[ack]'.encode():
        buf = fd.read(_readsize)
        while buf:
            #client.send(buf)
            client.send(buf)
            buf = fd.read(_readsize)
        fd.close()
        client.send('[done]'.encode())
        return 1
    else:
        fd.close()
        return 0

def recvfile(file, client):
    try:
        fd = open(file, 'wb+')
    except:
        _media_error('Can not open specific file for receiving')
        return 0

    # ready give me the info
    client.send('[ack]'.encode())
    #buf = client.recv(_readsize)
    buf = client.recv(_readsize)
    while buf:
        if buf != '[done]'.encode():
            fd.write(buf)
            buf = client.recv(_readsize)
        else:
            fd.close()
            return 1
    return 0

Этот подход предполагает, что все машины в сети имеют одинаковую endianness .

Кроме того, вам может понадобиться рассмотреть специальные текстовые файлы, если вы перемещаетесь между компьютерами с разными кодировками по умолчанию. Например, на компьютерах с Windows обычно используется cp1252 по умолчанию, современные Linux UTF-8. В этой ситуации вам нужно выбрать кодировку по умолчанию, которую следует использовать для передачи, и обрабатывать кодировки переключения на каждой стороне.

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