1

在 zstd 情况下,我遇到了一些解压问题。我有 hdf5 格式的文件,以下列方式压缩:

import h5py as h5
import hdf5plugin
import sys
import os
filefrom = sys.argv[1] 
h5path  = sys.argv[2]
f = h5.File(filefrom,'r')
data = f[h5path]
shape_data = data.shape[1:]
num = data.shape[0]
initShape = (1,) + shape_data
maxShape = (num,) + shape_data
f_zstd = h5.File(filefrom.split('.')[0]+'_zstd.h5','w')
d_zstd = f_zstd.create_dataset(path_to_data, initShape, maxshape=maxShape, dtype=np.int32, chunks=initShape, **hdf5plugin.Zstd())
d_zstd[0,] = data[0,]
for i in range(num):
    d_zstd.resize((i+1,) + shape_data)
    d_zstd[i,] = data[i,]
f_zstd.close()
f.close()
    

所以它压缩时没有任何错误,但是当我尝试使用它查看数据时,h5ls或者h5dump它打印出我无法打印数据,并且没有其他方法可以查看文件内部,例如使用 h5py 在 python3 (3.6) 中读取这个压缩数据不成功。我还尝试了h5repack( h5repack -i compressed_file.h5 -o out_file.h5 --filter=var:NONE) 或以下代码:

import zstandard
import pathlib
import os

def decompress_zstandard_to_folder(input_file):
    input_file = pathlib.Path(input_file)
    destination_dir = os.path.dirname(input_file)
    with open(input_file, 'rb') as compressed:
        decomp = zstandard.ZstdDecompressor()
        output_path = pathlib.Path(destination_dir) / input_file.stem
        with open(output_path, 'wb') as destination:
            decomp.copy_stream(compressed, destination)

什么都没有成功。在h5repack没有出现警告或错误的情况下,我得到了最后一段代码zstd.ZstdError: zstd decompressor error: Unknown frame descriptor,所以我得到这意味着压缩数据没有适当的标题。

我用python 3.6.7, hdf5 1.10.5。所以我有点困惑,不知道如何克服这个问题。

任何想法/建议都会很高兴!

4

1 回答 1

1

我编写了一个简单的测试来验证 zstd 压缩行为与一个简单的数据集(int32 的 NumPy 数组)。我可以用 h5py 打开 HDF5 文件并读取数据集。(注意:我无法使用 HDFView 打开,并且 h5repack 只报告形状和类型属性,而不是数据。)

我怀疑您的代码的另一部分存在未检测到的错误。您是否在没有 zstd 压缩的情况下测试了您的代码逻辑?如果没有,我建议你从那里开始。

编写示例文件的代码:

import h5py as h5
import hdf5plugin
import numpy as np

data = np.arange(1_000).reshape(100,10)

with h5.File('test_zstd.h5','w') as f_zstd:
    d_zstd = f_zstd.create_dataset('zstd_data', data=data, **hdf5plugin.Zstd())

读取示例文件的代码:

import h5py as h5
import hdf5plugin  ## Note: plugin required to read

with h5.File('test_zstd.h5','r') as f_zstd:
    d_zstd = f_zstd['zstd_data']
    print(d_zstd.shape, d_zstd.dtype)
    print(d_zstd[0,:])
    print(d_zstd[-1,:])

上面的输出:

(100, 10) int32
[0 1 2 3 4 5 6 7 8 9]
[990 991 992 993 994 995 996 997 998 999]

有关 HDF5 和压缩的更多信息:
要使用 HDF5 实用程序(如 h5repack)读取压缩文件,HDF5 安装需要适当的压缩过滤器。有些是标准的,许多(包括 xstandard)需要您安装第三方过滤器。可用插件的链接在这里:HDF5 Registered Filter Plugins

您可以通过添加标志来使用 h5dump 验证压缩过滤器-pH,如下所示:

E:\SO_68526704>h5dump -pH test_zstd.h5
HDF5 "test_zstd.h5" {
GROUP "/" {
   DATASET "zstd_data" {
      DATATYPE  H5T_STD_I32LE
      DATASPACE  SIMPLE { ( 100, 10 ) / ( 100, 10 ) }
      STORAGE_LAYOUT {
         CHUNKED ( 100, 10 )
         SIZE 1905 (2.100:1 COMPRESSION)
      }
      FILTERS {
         USER_DEFINED_FILTER {
            FILTER_ID 32015
            COMMENT Zstandard compression: http://www.zstd.net
         }
      }
      FILLVALUE {
         FILL_TIME H5D_FILL_TIME_ALLOC
         VALUE  H5D_FILL_VALUE_DEFAULT
      }
      ALLOCATION_TIME {
         H5D_ALLOC_TIME_INCR
      }
   }
}
}
于 2021-07-26T14:26:34.017 回答