Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/358.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在python3中解码压缩文件_Python_Json_Compression_Python 3.6 - Fatal编程技术网

在python3中解码压缩文件

在python3中解码压缩文件,python,json,compression,python-3.6,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.c

因此,我正在压缩一个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。

您做错了两件事:

  • 您试图将压缩数据视为UTF-8。它不是UTF-8,而是二进制数据。首先解压缩,然后解码为UTF-8

  • 您没有创建压缩的JSON。您正在创建压缩的Python数据表示形式。如果要编写压缩的JSON,请不要将JSON解码为Python

可以直接压缩JSON数据,无需解码;我会将其分块直接写入输出文件,以保持内存使用效率:

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)
请注意,我以二进制方式打开输入文件,没有理由仅仅为了压缩而对UTF-8中的数据进行解码(以文本模式打开文件就可以了)

要使用Python再次解码压缩的JSON,只需再次使用打开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

,则您做错了两件事:

  • 您试图将压缩数据视为UTF-8。它不是UTF-8,而是二进制数据。首先解压缩,然后解码为UTF-8

  • 您没有创建压缩的JSON。您正在创建压缩的Python数据表示形式。如果要编写压缩的JSON,请不要将JSON解码为Python

可以直接压缩JSON数据,无需解码;我会将其分块直接写入输出文件,以保持内存使用效率:

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)
请注意,我以二进制方式打开输入文件,没有理由仅仅为了压缩而对UTF-8中的数据进行解码(以文本模式打开文件就可以了)

要使用Python再次解码压缩的JSON,只需再次使用打开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

时,根本不需要使用json模块:只需压缩json文件数据即可。但是,通过将JSON加载到Python对象中并将其转换回JSON,可以消除多余的空白。您还可以执行其他转换,例如确保数据是ASCII安全的

正如Martijn所说,您应该压缩JSON数据,而不是用JSON数据加载的Python对象的str表示。要解压缩这些数据,需要调用decompress方法
.decode('utf-8')
将utf-8字节解码为Unicode字符串对象

这里有一个简短的演示。为了测试它,我创建了这个小小的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)
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}]
请注意,压缩版本实际上比压缩数据大(尽管两者都比原始数据小)。在压缩如此少量的数据时,这是意料之中的

完全不需要使用json模块:只需压缩json文件数据即可。但是,通过将JSON加载到Python对象中并将其转换回JSON,可以消除多余的空白。您还可以执行其他转换,例如确保数据是ASCII安全的

正如Martijn所说,您应该压缩JSON数据,而不是用JSON数据加载的Python对象的str表示。要解压缩这些数据,需要调用decompress方法
.decode('utf-8')
将utf-8字节解码为Unicode字符串对象

这里有一个简短的演示。为了测试它,我创建了这个小小的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)
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}]

请注意,压缩版本实际上比压缩数据大(尽管两者都比原始数据小)。在压缩如此少量的数据时,这是意料之中的

为什么要压缩Python表示呢。你不应该使用
json.load()
然后
str()
@MartijnPieters好吧,我对这方面还不熟悉。我的目标是压缩JSON。应该采用什么方法?为什么要压缩Python表示。你不应该使用
json.load()
然后
str()
@MartijnPieters好吧,我对这方面还不熟悉。我的目标是压缩JSON。应该采取什么办法?