读取文件时出错 -- 'utf' 无法解码位置 45 中的字节 0xff:起始字节无效
Error reading file -- 'utf' can't decode byte 0xff in position 45: invalid start byte
我这里有这两个脚本,send.py 和 receive.py。 Send.py 是主机,它打开连接并等待 receive.py 连接。一旦连接成功,理论上,我可以将任何文件从一台设备(使用 send.py 脚本)发送到另一台设备(使用 receive.py 脚本)。小问题......我试图从我在计算机上找到的随机音乐文件中读取以确保它适用于任何类型的文件并遇到以下错误:
UnicodeDecodeError: 'utf-8' codec can't decode byte 0xff in position 45: invalid start byte
导致此错误的原因是什么?
send.py:
from socket import *
port = 42069
s = socket(AF_INET, SOCK_STREAM)
s.bind(('0.0.0.0', port))
s.listen(1)
c, addr = s.accept()
buffersize = 128
fname = '✵ТГК -Гелик 2022✵ Gelik✵-160 (mp3cut.net).mp3' #input('File Path: ')
with open(fname, 'rb') as file:
readfc = file.read()
c.send(fname.encode())
if len(readfc) > buffersize:
for packet in range(len(readfc) % buffersize):
c.send(readfc[0:buffersize])
和receive.py:
from socket import *
port = 42069
s = socket(AF_INET, SOCK_STREAM)
s.connect(('192.168.0.171', port))
index = 0
while True:
data = s.recv(1024)
if not data:
pass
else:
index += 1
if index == 1:
filename = data.decode()
else:
with open(filename, 'ab') as file:
file.write(data.decode())
这里是 msuic 文件的第一行:
ID3 #TSSE Lavf59.16.100 яыа Info #R ђ.3
!$&)+.0369:=@CEGJMORUVY\_acfiknqsux{}Ђ‚…‡ЉЌЏ‘”—љњћЎЈ¦©«°і¶ёєЅАВЕЗКМПТФЦЩЬЮбгжилортхшъэ Lavc59.18 $@ ђ.3ЮЬмf яыаD р i ```
此代码假设发件人中的单个 send
与收件人中的单个 recv
匹配。这个假设对于 TCP 是错误的:TCP 只是一个非结构化的字节流,而不是一个结构化的消息传输,它会在 send/recv.
上保留消息边界。
这意味着收件人的首字母 data = s.recv(1024)
可能不仅包括文件名,而且可能已经包括部分音乐文件。因此它是 utf-8 编码文件名(multi-byte 个字符)后跟二进制音乐数据(字节)的混合体。尝试 filename = data.decode()
将成功解码初始文件名。但它会在文件名结束后继续解码数据,从而将二进制音乐数据也视为以 utf-8 编码的 multi-byte 字符。这将导致观察到的解码错误。
解决方法应该是清楚地标记文件名结束的位置和二进制数据的开始位置,然后只将文件名解码为文本并将其余部分视为字节。一种常见的方法是在文件名前加上长度前缀,以便清楚地知道它在哪里结束。另一种方法可能是在文件名末尾添加一个 [=14=]
(因为它不是有效的 utf-8 编码字符的一部分,除了 NUL - 它本身在文件名中是无效的)并将传入数据拆分为这个分隔符。
除此之外,后面的 data.decode()
在读取音乐数据时显然是错误的,因为发送方没有匹配的 encode()
。而且不应该有一个,因为这些是二进制数据,即已经是字节。
除了@StefanUllrich 所说的:
您在第 9 行收到二进制数据。
您在第 17 行以二进制模式打开文件。
所有这些都是正确的。
为什么你认为你需要在第 18 行将二进制数据解码为字符串???这就是导致您看到的异常的原因。只是不要调用 .decode()
,按原样写入数据!
我这里有这两个脚本,send.py 和 receive.py。 Send.py 是主机,它打开连接并等待 receive.py 连接。一旦连接成功,理论上,我可以将任何文件从一台设备(使用 send.py 脚本)发送到另一台设备(使用 receive.py 脚本)。小问题......我试图从我在计算机上找到的随机音乐文件中读取以确保它适用于任何类型的文件并遇到以下错误:
UnicodeDecodeError: 'utf-8' codec can't decode byte 0xff in position 45: invalid start byte
导致此错误的原因是什么?
send.py:
from socket import *
port = 42069
s = socket(AF_INET, SOCK_STREAM)
s.bind(('0.0.0.0', port))
s.listen(1)
c, addr = s.accept()
buffersize = 128
fname = '✵ТГК -Гелик 2022✵ Gelik✵-160 (mp3cut.net).mp3' #input('File Path: ')
with open(fname, 'rb') as file:
readfc = file.read()
c.send(fname.encode())
if len(readfc) > buffersize:
for packet in range(len(readfc) % buffersize):
c.send(readfc[0:buffersize])
和receive.py:
from socket import *
port = 42069
s = socket(AF_INET, SOCK_STREAM)
s.connect(('192.168.0.171', port))
index = 0
while True:
data = s.recv(1024)
if not data:
pass
else:
index += 1
if index == 1:
filename = data.decode()
else:
with open(filename, 'ab') as file:
file.write(data.decode())
这里是 msuic 文件的第一行:
ID3 #TSSE Lavf59.16.100 яыа Info #R ђ.3
!$&)+.0369:=@CEGJMORUVY\_acfiknqsux{}Ђ‚…‡ЉЌЏ‘”—љњћЎЈ¦©«°і¶ёєЅАВЕЗКМПТФЦЩЬЮбгжилортхшъэ Lavc59.18 $@ ђ.3ЮЬмf яыаD р i ```
此代码假设发件人中的单个 send
与收件人中的单个 recv
匹配。这个假设对于 TCP 是错误的:TCP 只是一个非结构化的字节流,而不是一个结构化的消息传输,它会在 send/recv.
这意味着收件人的首字母 data = s.recv(1024)
可能不仅包括文件名,而且可能已经包括部分音乐文件。因此它是 utf-8 编码文件名(multi-byte 个字符)后跟二进制音乐数据(字节)的混合体。尝试 filename = data.decode()
将成功解码初始文件名。但它会在文件名结束后继续解码数据,从而将二进制音乐数据也视为以 utf-8 编码的 multi-byte 字符。这将导致观察到的解码错误。
解决方法应该是清楚地标记文件名结束的位置和二进制数据的开始位置,然后只将文件名解码为文本并将其余部分视为字节。一种常见的方法是在文件名前加上长度前缀,以便清楚地知道它在哪里结束。另一种方法可能是在文件名末尾添加一个 [=14=]
(因为它不是有效的 utf-8 编码字符的一部分,除了 NUL - 它本身在文件名中是无效的)并将传入数据拆分为这个分隔符。
除此之外,后面的 data.decode()
在读取音乐数据时显然是错误的,因为发送方没有匹配的 encode()
。而且不应该有一个,因为这些是二进制数据,即已经是字节。
除了@StefanUllrich 所说的:
您在第 9 行收到二进制数据。
您在第 17 行以二进制模式打开文件。
所有这些都是正确的。
为什么你认为你需要在第 18 行将二进制数据解码为字符串???这就是导致您看到的异常的原因。只是不要调用 .decode()
,按原样写入数据!