首页 > 解决方案 > 在 python3 中通过 tcp 套接字发送不同的文件类型,给出 'UnicodeDecodeError'

问题描述

编写一个小型应用程序,让我可以在家中通过 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

(忽略杂乱的回报,我稍后会修复这些)

标签: python-3.xsocketsencodingtcp

解决方案


由于您通过网络发送字节,因此最简单的方法是专门使用字节。

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

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

这种方法假设网络上的所有机器共享相同的字节序

此外,如果您在具有不同默认编码的机器之间传输,您可能需要考虑特殊大小写的文本文件。例如,Windows 机器倾向于将 cp1252 作为默认的现代 Linux UTF-8。在这种情况下,您需要确定用于传输的默认编码,并在每一侧处理切换编码。


推荐阅读