所以,我正在压缩JSON文件。
import json
import gzip
with open('big.json','r') as fid_json:
# get json as type dict
json_dict = json.load(fid_json)
# convert dict to str
json_str = str(json_dict)
json_bytes = bytes(json_str,'utf8')
x = gzip.compress(json_bytes)
那么我可以解码压缩的字节文件吗?我正在尝试这个
json_str = x.decode('utf-8')
但这会产生错误。
UnicodeDecodeError: 'utf-8' codec can't decode byte 0x8b in position 1: invalid start byte
我认为我在做一些理论上的错误或者我能解码压缩文件吗? 我怎样才能获得压缩的JSON文件,因为我只想压缩JSON?我正在使用python3。
答案 0 :(得分:3)
你做错了两件事:
您正在尝试将压缩数据视为UTF-8。它不是UTF-8,它是二进制数据。首先解压缩 ,然后解码为UTF-8。
您没有创建压缩的JSON。您正在创建压缩的 Python数据表示。如果要编写压缩的JSON,请不要将JSON解码为Python。
您可以直接压缩JSON数据而无需解码;我将 chunks 直接添加到输出文件中以保持内存使用效率:
import gzip
import shutil
with open('big.json', 'rb') as fid_json, gzip.open('big.json.gz', 'wb') as out:
shutil.copyfileobj(fid_json, out)
请注意,我打开输入文件为 binary ,没有理由解码来自UTF-8的数据只是为了压缩它(在文本模式下打开文件会这样做)。
要使用Python再次解码压缩的JSON,只需再次打开带有gzip.open()
function的gzip压缩文件,这次是在文本模式下:
import gzip
import json
with gzip.open('big.json.gz', 'r', encoding='utf8') as fid_json:
data = json.load(fid_json)
gzip.open()
返回的GZIP文件对象为您处理压缩和UTF-8解码; json.load()
函数可以从那里解压缩包含的JSON文档。
明确说明文件的编码总是一个好主意,而不是依赖于为打开的每个文件正确设置的语言环境。也就是说,从Python 3.6 json.load()
开始,它也接受二进制输入,并检测使用了什么UTF编码,所以在这种情况下使用:
import gzip
import json
with gzip.open('big.json.gz') as fid_json:
data = json.load(fid_json)
默认模式为rb
。
答案 1 :(得分:0)
你 根本不需要使用json模块:你可以简单地压缩JSON文件数据。但是,通过将JSON加载到Python对象&将它转换回JSON你可以摆脱多余的空白。您还可以执行其他转换,例如,确保数据是ASCII安全的。
正如Martijn所说,您应该压缩JSON数据而不是您使用JSON数据加载的Python对象的str表示。要解压缩该数据,您需要调用解压缩方法。 .decode('utf-8')
将UTF-8字节解码为Unicode字符串对象。
这是一个简短的演示。为了测试它,我创建了这个小JSON文件。
<强> test.json 强>
[
{
"name": "PM 2Ring",
"id": 4014959
},
{
"name": "Dan ish",
"id": 6390698
}
]
这是代码。
import json
import gzip
fname = 'test.json'
# Load JSON data into a Python object
with open(fname) as fid_json:
json_dict = json.load(fid_json)
#Convert to a single line JSON string, and encode the string to bytes
json_bytes = json.dumps(json_dict).encode('utf-8')
print(json_bytes)
print('Compressed')
x = gzip.compress(json_bytes)
print(x)
print('Length:', len(x))
print('Decompressed')
new_json = gzip.decompress(x).decode('utf-8')
print(new_json)
print('Length:', len(new_json))
# Load it into a Python object
obj = json.loads(new_json)
print(obj)
<强>输出强>
b'[{"name": "PM 2Ring", "id": 4014959}, {"name": "Dan ish", "id": 6390698}]'
Compressed
b'\x1f\x8b\x08\x00k\x0e1Y\x02\xff\x8b\xaeV\xcaK\xccMU\xb2RP\n\xf0U0\n\xca\xccKW\xd2QP\xcaL\x01\x8a\x98\x18\x18\x9aX\x9aZ\xd6\xea( \x14\xb9$\xe6)d\x16g\xc0\xd5\x98\x19[\x1a\x98YZ\xd4\xc6\x02\x00v4\x00SI\x00\x00\x00'
Length: 77
Decompressed
[{"name": "PM 2Ring", "id": 4014959}, {"name": "Dan ish", "id": 6390698}]
Length: 73
[{'name': 'PM 2Ring', 'id': 4014959}, {'name': 'Dan ish', 'id': 6390698}]
请注意,压缩版本实际上大于压缩数据(尽管两者都小于原始数据)。在压缩如此少量的数据时可以预料到这一点。