通过python3中的tcp套接字发送不同的文件类型,会给出“ UnicodeDecodeError”

时间:2019-03-29 17:12:14

标签: python-3.x sockets encoding tcp

编写一个小型应用程序,使我可以在家中通过LAN网络共享文件,而不会太麻烦,所以我想支持所有文件扩展名。

当发送文本文件时,我使用.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 个答案:

答案 0 :(得分:1)

由于您是通过网络发送字节,所以仅使用字节进行操作最简单。

以二进制模式打开文件,并且不对文件数据进行编码或解码。您仍然需要对确认/完成的邮件进行编码。

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。在这种情况下,您需要确定用于传输的默认编码,并处理每一侧的切换编码。