【问题标题】:Safest way to save binary file with numpy to be read使用要读取的 numpy 保存二进制文件的最安全方法
【发布时间】:2015-10-30 00:55:03
【问题描述】:

我需要使用 numpy 保存一些数组,以便稍后使用 Android Java APP 和另一个使用 numpy 的 python 应用程序读取。到目前为止,我一直在为 io 使用 numpy.ndarray.tofile 和 numpy.ndarray.fromfile,由于它们的简单性,我非常喜欢这两个。我编写和读取此类二进制数组的解决方案是:

def write_feature_bin_file(filepath, features_list):

if os.path.isfile(filepath):
    os.remove(filepath)

allfeatures = numpy.vstack(features_list)
header = [allfeatures.shape[0]]
try:
    header.append(allfeatures.shape[1])
except Exception as e:
    header.append(1)

if allfeatures.dtype.name == 'uint8':
    header.append(0)
else:
    header.append(5)

header = numpy.array(header, dtype=numpy.int32)

try:
    binf = open(filepath, 'a')
    header.tofile(binf)
    allfeatures.tofile(binf)
    binf.close()
except Exception as e:
    print "Unable to save file: ", filepath
    print e

return

def read_feature_bin_file(filepath):

try:
    binf = open(filepath, 'r')

    header = numpy.fromfile(f, count=3, dtype=numpy.int32)
    print header

    rows = header[0]
    cols = header[1]
    dt = header[2]


    if dt == 0:
        features = numpy.fromfile(f, dtype=numpy.uint8)
    else:
        features = numpy.fromfile(f, dtype=numpy.float32)

    features.resize(rows, cols)
    binf.close()

    return features

except Exception as e:

    print "Unable to read file: ", filepath
    print e
    return None

我在这里所做的只是将一个小标题写入输出文件,包含三个整数,描述行数、列数和数据类型,可以是 uint8 或 float32,然后附加其余部分我的数据到文件。读取时,我读取头的前三个元素以检查数组属性,然后相应地读取文件的其余部分。问题是:我不知道这是否安全,尤其是关于要读取此文件的系统的字节序。

对我来说,确保可以在任何系统中正确读取此文件的最佳方法是什么?我知道 numpy 具有“保存”和“加载”功能,它们都以 .npz 或 .npy 格式保存,但我不知道如何将它们移植到我的 Android 应用程序中读取。

【问题讨论】:

标签: android python arrays numpy binary


【解决方案1】:

two main options.

1.始终以相同的字节顺序保存

您可以将字节序严格定义为文件格式规范的一部分,并相应地对文件读取器和写入器进行编程。 例如,使用 Numpy,您可以将字节顺序指定为 dtype character code 的一部分:<f4 表示小端 4 字节浮点数 (=float32),>f4 表示大端。为了始终以 little-endian 格式编写,编写例程可以包含如下内容:

if allfeatures.dtype.name == 'uint8':
    header.append(0)
else:
    allfeatures = allfeatures.astype('<f4', copy=False)
    header.append(5)

header = numpy.array(header, dtype='<i4')

2。在文件头中指定字节序

这就是 Numpy .npy 格式在幕后实现的(它存储了 ndarray.dtype.descr 返回的 dtype 字符代码)。 .npy 格式在 Numpy 中非常易于使用,但在 Java 应用程序中可能不那么容易使用。所以也许最简单但仍然可靠的解决方案是在标题前面存储一个额外的标志。这样,在从标头中读取数组维度之前,就可以轻松确定字节顺序。

另外,从当前标头中的第三个标志确定字节顺序也是有意义的,但是您必须更改 uint8 的标识符(零在大端和小端中具有相同的表示,所以不能使用)。可以这样编程:

def read_feature_bin_file(filepath):

    with open(filepath, 'rb') as binf:
        header = numpy.fromfile(binf, count=3, dtype='<i4')
        if header[2] not in [1, 5]:  # Check endianness
            header = header.view('>i4')

        rows, cols, dt = header
        dtype = 'u1' if dt==1 else header.dtype.byteorder + 'f4'
        features = numpy.fromfile(binf, dtype)

    features.shape = (rows, cols)
    return features

【讨论】:

  • 谢谢!我特别喜欢在标头的格式化标志上进行编码,非常聪明的解决方案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-08-02
  • 1970-01-01
  • 2016-08-30
  • 1970-01-01
  • 1970-01-01
  • 2013-04-07
相关资源
最近更新 更多