- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
是否可以通过套接字发送包含文件(图像或文档)作为值的字典?
我试过像下面这样的东西但我失败了..
with open("cat.jpeg", "rb") as f:
myFile = f.read(2048)
data = {"id": "1283", "filename": "cat.jpeg", "file": myFile}
dataToSend = json.dumps(data).encode("utf-8")
这给出了一个 json 错误,myFile 是一个字节数组,无法序列化。
我尝试使用 base64 编码将 myFile 转换为字符串,但没有成功。
部分起作用的是将 myFile 转换为字符串,例如 str(myFile)。 json 序列化器工作,我通过套接字发送它,dict 没问题,但 myFile 数据已损坏,所以我无法重新创建图片。
那么是否可以使用这种方法或者我应该如何通过套接字发送文件和数据以便在另一端轻松解析?
乐:
仍然无法使用 base64 编码,myFile 仍然是“字节”格式并且json 给出了这个错误:TypeError: Object of type 'bytes' is not JSON serializable
客户端
import os
import base64
import json
import socket
currentPath = os.path.dirname(os.path.abspath(__file__)) + "\\downloads\\"
with open(currentPath + "cat.png", "rb") as f:
l = f.read()
print(type(l)) #prints <class 'bytes'>
myFile = base64.b64encode(l)
print(type(myFile)) #prints <class 'bytes'>
data = {"id": "12", "filename": "cat.png", "message": "So cute!", "file": myFile}
dataToSend = json.dumps(data).encode("utf-8") #prints TypeError: Object of type 'bytes' is not JSON serializable
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(("127.0.0.1", 1234))
s.sendall(dataToSend)
s.close()
和服务器:
import socket
import json
import os
import sys
import time
import base64
currentPath = os.path.dirname(os.path.abspath(__file__)) + "\\fileCache\\"
tempData = bytearray()
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind(("127.0.0.1", 1234))
s.listen(5)
conn, addr = s.accept()
while True:
dataReceived = conn.recv(2048)
if sys.getsizeof(dataReceived) > 17:
tempData = tempData + dataReceived
else:
data = json.loads(tempData.decode("utf-8"))
break
time.sleep(1)
print(data)
myFile = base64.b64decode(data["file"])
with open(currentPath + data["filename"], "wb") as f:
f.write(myFile)
f.close()
最佳答案
正如我在评论中所说,将二进制数据打包成字符串格式(如 JSON)是一种浪费——如果你使用 base64,你会增加 33% 的数据传输大小,这也会让 JSON 解码器难以处理正确解码 JSON,因为它需要流式传输整个结构以提取索引。
最好单独发送它们 - JSON 作为 JSON,然后文件内容直接作为二进制。当然,您需要一种方法来区分两者,最简单的方法是在发送 JSON 数据时在其前面加上长度,以便服务器知道要读取多少字节才能获取 JSON,然后读取其余部分作为文件内容。这将使它成为一种非常简单的协议(protocol),其包的形式如下:
[JSON LENGTH][JSON][FILE CONTENTS]
假设 JSON 永远不会大于 4GB(如果是,您将遇到更大的问题,因为解析它会是一场噩梦)拥有 JSON LENGTH
就足够了固定的 4 个字节(32 位)作为一个无符号整数(如果你不希望 JSON 超过 64KB,你甚至可以选择 16 位)所以整个策略将在客户端工作:
bytes
在服务器端你做同样的过程
或者在代码中,客户端:
import json
import os
import socket
import struct
BUFFER_SIZE = 4096 # a uniform buffer size to use for our transfers
# pick up an absolute path from the script folder, not necessary tho
file_path = os.path.abspath(os.path.join(os.path.dirname(__file__), "downloads", "cat.png"))
# let's first prepare the payload to send over
payload = {"id": 12, "filename": os.path.basename(file_path), "message": "So cute!"}
# now JSON encode it and then turn it onto a bytes stream by encoding it as UTF-8
json_data = json.dumps(payload).encode("utf-8")
# then connect to the server and send everything
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s: # create a socket
print("Connecting...")
s.connect(("127.0.0.1", 1234)) # connect to the server
# first send the JSON payload length
print("Sending `{filename}` with a message: {message}.".format(**payload))
s.sendall(struct.pack(">I", len(json_data))) # pack as BE 32-bit unsigned int
# now send the JSON payload itself
s.sendall(json_data) # let Python deal with the buffer on its own for the JSON...
# finally, open the file and 'stream' it to the socket
with open(file_path, "rb") as f:
chunk = f.read(BUFFER_SIZE)
while chunk:
s.send(chunk)
chunk = f.read(BUFFER_SIZE)
# alternatively, if you're using Python 3.5+ you can just use socket.sendfile() instead
print("Sent.")
和服务器:
import json
import os
import socket
import struct
BUFFER_SIZE = 4096 # a uniform buffer size to use for our transfers
target_path = os.path.abspath(os.path.join(os.path.dirname(__file__), "fileCache"))
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.bind(("127.0.0.1", 1234)) # bind to the 1234 port on localhost
s.listen(0) # allow only one connection so we don't have to deal with data separation
while True:
print("Waiting for a connection...")
connection, address = s.accept() # wait for and accept the incoming connection
print("Connection from `{}` accepted.".format(address))
# read the starting 32 bits and unpack them into an int to get the JSON length
json_length = struct.unpack(">I", connection.recv(4))[0]
# now read the JSON data of the given size and JSON decode it
json_data = b"" # initiate an empty bytes structure
while len(json_data) < json_length:
chunk = connection.recv(min(BUFFER_SIZE, json_length - len(json_data)))
if not chunk: # no data, possibly broken connection/bad protocol
break # just exit for now, you should deal with this case in production
json_data += chunk
payload = json.loads(json_data.decode("utf-8")) # JSON decode the payload
# now read the rest and store it into a file at the target path
file_path = os.path.join(target_path, payload["filename"])
with open(file_path, "wb") as f: # open the target file for writing...
chunk = connection.recv(BUFFER_SIZE) # and stream the socket data to it...
while chunk:
f.write(chunk)
chunk = connection.recv(BUFFER_SIZE)
# finally, lets print out that we received the data
print("Received `{filename}` with a message: {message}".format(**payload))
注意:请记住,这是 Python 3.x 代码 - 对于 Python 2.x,您必须自己处理上下文管理,而不是打开 with ...
block /关闭你的套接字。
这就是它的全部。当然,在真实环境中,您需要处理断开连接、多个客户端等问题。但这是基本过程。
关于python - 通过套接字发送包含文件的字典(python),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50659391/
我只想国家和资本化的值(value)。 这是我的完整代码: cities = { 'rotterdam': { 'country': 'netherlands',
想更好地了解如何比较对象类型的键。 dicOverall.exists(dic2) 返回 False,而 dicOverall.exists(dic1) 返回 True。我不太确定 .Exists 如
我是编程和 python 的新手,我不知道如何解决这个问题。 my_dict = {'tiger': ['claws', 'sharp teeth', 'four legs', 'stripes'
这个问题已经有答案了: Accessing an object property with a dynamically-computed name (19 个回答) 已关闭 8 年前。 我引用了这篇文
希望有人能帮忙。我正在使用 Python,我希望能够执行以下操作。 我有一组对象(例如形状)和一系列作用于这些对象的命令。命令的格式为命令字符串,后跟可变数量的参数,可以是字符串或整数 例如形状“矩形
我在文件中保存了一本字典。我从 python 交互式 shell 将字典加载到内存中,我的系统监视器显示 python 进程消耗了 4GB。以下命令提供以下输出: size1 = sys.getsiz
如果我运行以下代码: import json foo = [ { "name": "Bob", "occupation": "", "stand
我尝试获取列名及其索引,并将结果保存为数据框或字典: df <- data.frame(a=rnorm(10), b=rnorm(10), c=rnorm(10)) 我该怎么做?谢谢。 column
我正在尝试获取输入,如果字典 logins 有一个与我的输入匹配的键,我想返回该键的值。 logins = { 'admin':'admin', 'turtle':'password1
在 Perl 世界中有一个很棒的东西叫做 CPAN .它是开源 Perl 库的大型存储。 我使用来自 CPAN 的模块,我已经发布了 several distributions myself . 我使
这个问题已经有答案了: Is there a Python dict without values? (3 个回答) 已关闭 3 年前。 我有一个问题,我想跟踪大量值。如果我从未遇到过该值,我将执行操
想知道这是否可能。 我们有一个第 3 方库,其中包含有关用户的识别信息... 与库的主要交互是通过一个以字符串为键的 HashTable,并返回该键的信息对象图。 问题是, key 显然是区分大小写的
我是 .NET 编程的新手。对不起,如果这个问题以前被问过。 我目前正在学习 F#。 Dictionary、Hashtable 和 Map 之间有什么区别?我应该什么时候使用? 我还有一个标题中没有提
我正在尝试使用SVM进行3类分类。为此,我正在SVM培训期间准备词汇表。但是,由于我在SVM预测期间获得随机结果,因此我怀疑我的词汇创建方法中存在一些问题。我创建词汇的代码如下: //Mat trai
就目前情况而言,这个问题不太适合我们的问答形式。我们希望答案得到事实、引用资料或专业知识的支持,但这个问题可能会引发辩论、争论、民意调查或扩展讨论。如果您觉得这个问题可以改进并可能重新开放,visit
假设我有一个以下形式的嵌套字典: {'geo': {'bgcolor': 'white','lakecolor': 'white','caxis': {'gridcolor': 'white', 'l
我有一个 java 应用程序,每秒启动和停止数亿个项目(从外部脚本调用)多次。 Input: String key Output: int value 此应用程序的目的是在从未永远改变的Map(约30
我正在尝试找出字典与集合和数组相比的相对优势和功能。 我发现了一篇很棒的文章here但找不到一个简单的表格来比较所有不同的功能。 有人知道吗? 最佳答案 请参阅下表,对集合和字典进行有用的比较。 (该
我想要一个字典,它可以为字典中没有的任何键返回一个指定的值,例如: var dict = new DictWithDefValues("not specified"); dict.Add("bob78
我是 python 新手,目前仍在学习如何处理列表和字典。 我有这两个功能 def food_database(item_name, size_serv, calorie_serv, prot
我是一名优秀的程序员,十分优秀!