在python3中解码压缩文件

时间:2017-06-02 06:24:46

标签: python json compression python-3.6

所以,我正在压缩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。

2 个答案:

答案 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}]

请注意,压缩版本实际上大于压缩数据(尽管两者都小于原始数据)。在压缩如此少量的数据时可以预料到这一点。