【Numpy核心编程攻略:Python数据处理、分析详解与科学计算】1.14 文件IO大师:二进制存储的进阶技巧

在这里插入图片描述

1.14 文件IO大师:二进制存储的进阶技巧

目录
Syntax error in textmermaid version 10.9.0
1.14.1 NPY文件格式结构解析

NumPy 提供了 npy 文件格式来存储数组数据。本节将详细介绍 npy 文件的结构,并通过示例进行展示。

Syntax error in textmermaid version 10.9.0
1.14.1.1 NPY文件头结构

npy 文件头包含了一些元数据信息,这些信息用于描述数组的形状、数据类型和字节序等。文件头的结构如下:

  • 魔数(Magic Number):前6个字节,表示文件格式版本。
  • 版本号(Version):2个字节,表示文件格式的主版本号和次版本号。
  • 字节序(Byte Order):1个字节,表示数据的字节序(大端或小端)。
  • 字节长度(Byte Length):4个字节,表示文件头的字节长度。
  • 描述符(Descriptor):JSON格式的字符串,包含数组的形状、数据类型等信息。
1.14.1.2 NPY文件格式示例
import numpy as np

# 创建一个 3x3 的数组
data = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])

# 保存为 npy 文件
np.save('data.npy', data)

# 读取 npy 文件
loaded_data = np.load('data.npy')
print("从 npy 文件读取的数据:\n", loaded_data)
1.14.1.3 NPY文件头结构解析示意图
Syntax error in textmermaid version 10.9.0
1.14.2 内存映射文件处理大型数据集

在处理大型数据集时,内存映射文件(Memory-Mapped File)是一个非常有用的工具。本节将详细介绍如何使用 NumPy 的内存映射功能来处理10GB级的数据集。

1.14.2.1 内存映射文件的基本原理

内存映射文件允许你在不将整个文件加载到内存的情况下,访问和修改文件中的数据。这对于处理大型数据集非常有用,因为它可以显著减少内存使用量。

1.14.2.2 使用mmap处理10GB级数据案例
import numpy as np
import os

# 创建一个 10GB 的文件
file_size = 10 * 1024 * 1024 * 1024  # 10GB
with open('large_data.dat', 'wb') as f:
    f.write(np.zeros(file_size, dtype=np.uint8))

# 使用内存映射文件
shape = (10000000, 1000)
dtype = np.float32

# 创建内存映射数组
mmap_array = np.memmap('large_data.dat', dtype=dtype, mode='r+', shape=shape)

# 访问和修改数据
mmap_array[0, 0] = 1.0  # 修改第一个元素
print("第一个元素: ", mmap_array[0, 0])  # 访问第一个元素

# 关闭内存映射数组
mmap_array.flush()
del mmap_array

# 删除文件
os.remove('large_data.dat')
1.14.2.3 内存映射文件的性能优势

内存映射文件的主要优势在于它可以按需加载数据,而不是一次性将整个文件加载到内存中。这可以显著减少内存使用量,并提高数据访问的效率。

1.14.3 跨平台字节序问题解决方案

在多平台环境下,字节序问题(endianness)是一个常见的问题。本节将介绍如何在 NumPy 中处理字节序问题,并通过位操作进行演示。

Syntax error in textmermaid version 10.9.0
1.14.3.1 字节序的基本概念
  • 大端字节序(Big-Endian):最高有效字节(MSB)存储在最低地址。
  • 小端字节序(Little-Endian):最低有效字节(LSB)存储在最低地址。
1.14.3.2 字节序转换的位操作演示
import numpy as np

# 创建一个 32 位整数数组
data = np.array([1, 2, 3, 4], dtype=np.uint32)

# 打印原始数据的字节序
print("原始数据的字节序: ", data.dtype.byteorder)

# 转换字节序
data_swapped = data.byteswap().newbyteorder()
print("转换字节序后的数据: ", data_swapped)

# 通过位操作进行字节序转换
def byteswap_uint32(value):
    """
    通过位操作转换 32 位整数的字节序

    :param value: 需要转换的 32 位整数
    :return: 转换字节序后的 32 位整数
    """
    return ((value & 0xFF000000) >> 24) | \
           ((value & 0x00FF0000) >> 8) | \
           ((value & 0x0000FF00) << 8) | \
           ((value & 0x000000FF) << 24)

# 测试位操作的字节序转换
original_value = 0x12345678
swapped_value = byteswap_uint32(original_value)
print(f"原始值: 0x{original_value:08X}, 转换后的值: 0x{swapped_value:08X}")
1.14.3.3 字节序转换的位操作示意图
Syntax error in textmermaid version 10.9.0
1.14.4 加密存储与数据压缩实战

在实际应用中,数据的安全性和存储效率是非常重要的。本节将介绍如何使用 NumPy 进行二进制文件的加密和压缩存储。

1.14.4.1 二进制文件加密的基本原理

数据加密通常使用对称加密算法,如 AES(Advanced Encryption Standard)。本节将介绍如何使用 PyCrypto 库进行二进制文件的加密。

1.14.4.2 使用zlib实现压缩存储

zlib 是一个常用的压缩库,可以用于压缩 NumPy 数组数据。本节将介绍如何使用 zlib 进行数据压缩和解压。

import numpy as np
import zlib

# 创建一个 1000x1000 的数组
data = np.random.rand(1000, 1000)

# 将数组转换为二进制字符串
data_binary = data.tobytes()

# 进行数据压缩
compressed_data = zlib.compress(data_binary)
print("压缩前的数据大小: ", len(data_binary), "字节")
print("压缩后的数据大小: ", len(compressed_data), "字节")

# 进行数据解压
decompressed_data = zlib.decompress(compressed_data)
decompressed_array = np.frombuffer(decompressed_data, dtype=data.dtype).reshape(data.shape)
print("解压后的数组形状: ", decompressed_array.shape)

# 验证解压后的数据是否与原始数据一致
assert np.array_equal(data, decompressed_array)
1.14.4.3 加密npy文件的完整方案
import numpy as np
import os
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad, unpad
import base64

# 生成密钥
key = os.urandom(32)  # 256 位密钥

# 定义加密函数
def encrypt_npy(file_path, key):
    """
    加密 npy 文件

    :param file_path: npy 文件路径
    :param key: 加密密钥
    :return: 加密后的文件路径
    """
    # 读取 npy 文件数据
    data = np.load(file_path)
    data_binary = data.tobytes()
    
    # 创建 AES 加密器
    cipher = AES.new(key, AES.MODE_CBC)
    
    # 进行数据加密
    encrypted_data = cipher.encrypt(pad(data_binary, AES.block_size))
    
    # 保存加密后的数据
    encrypted_file_path = file_path + '.enc'
    with open(encrypted_file_path, 'wb') as f:
        f.write(cipher.iv)  # 保存初始化向量
        f.write(encrypted_data)  # 保存加密后的数据
    
    return encrypted_file_path

# 定义解密函数
def decrypt_npy(file_path, key):
    """
    解密 npy 文件

    :param file_path: 加密后的 npy 文件路径
    :param key: 解密密钥
    :return: 解密后的数组
    """
    # 读取加密后的文件数据
    with open(file_path, 'rb') as f:
        iv = f.read(16)  # 读取初始化向量
        encrypted_data = f.read()
    
    # 创建 AES 解密器
    cipher = AES.new(key, AES.MODE_CBC, iv=iv)
    
    # 进行数据解密
    decrypted_data = unpad(cipher.decrypt(encrypted_data), AES.block_size)
    
    # 恢复数组
    original_shape = np.load(file_path[:-4] + '.npy').shape
    original_dtype = np.load(file_path[:-4] + '.npy').dtype
    decrypted_array = np.frombuffer(decrypted_data, dtype=original_dtype).reshape(original_shape)
    
    return decrypted_array

# 创建一个 npy 文件
data = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
np.save('data.npy', data)

# 加密 npy 文件
encrypted_file_path = encrypt_npy('data.npy', key)

# 解密 npy 文件
decrypted_data = decrypt_npy(encrypted_file_path, key)
print("解密后的数组:\n", decrypted_data)

# 删除文件
os.remove('data.npy')
os.remove(encrypted_file_path)
1.14.4.4 加密存储的注意事项
  • 密钥管理:确保密钥的安全性,避免泄露。
  • 性能:加密和解密操作会增加一定的性能开销,需要在安全性和性能之间进行权衡。
  • 文件格式:加密后的文件格式需要特别处理,确保在不同平台上的兼容性。
总结

通过本篇文章的详细讲解和示例,我们对 NumPy 中的文件IO操作有了更深入的理解。主要内容包括:

  1. NPY文件格式结构解析:介绍了 npy 文件头的结构,并通过示例进行了展示。
  2. 内存映射文件处理大型数据集:详细讲解了内存映射文件的基本原理,并通过一个10GB级数据的案例展示了其应用。
  3. 跨平台字节序问题解决方案:介绍了字节序的基本概念,并通过位操作进行了字节序转换的演示。
  4. 加密存储与数据压缩实战:介绍了如何使用 zlib 进行数据压缩,并通过 PyCrypto 库实现了 npy 文件的加密和解密。

希望这些内容对你有所帮助,如果你有任何问题或建议,欢迎在评论区留言。我们下一篇文章再见!

参考资料
资料名称链接
NumPy 官方文档https://numpy.org/doc/stable/
NPY 文件格式https://numpy.org/doc/stable/reference/generated/numpy.lib.format.html
内存映射文件https://numpy.org/doc/stable/reference/generated/numpy.memmap.html
Python 伪代码生成工具https://pypi.org/project/pygenstub/
字节序转换https://docs.scipy.org/doc/numpy-1.13.0/reference/generated/numpy.ndarray.byteswap.html
位操作示例https://www.geeksforgeeks.org/python-bitwise-operators/
PyCrypto 官方文档https://pycryptodome.readthedocs.io/en/latest/
AES 加密算法https://en.wikipedia.org/wiki/Advanced_Encryption_Standard
zlib 压缩库https://docs.python.org/3/library/zlib.html
跨平台字节序问题https://www.venusintel.com/73.html
内存映射文件性能https://stackoverflow.com/questions/56569529/what-is-the-difference-between-numpy-memmap-and-numpy-load-with-mmap-mode
二进制文件处理https://realpython.com/python-binary-files/
数据压缩https://towardsdatascience.com/data-compression-for-machine-learning-f3f9b91ebcf7

如果你觉得这篇文章对你有帮助,感谢点赞、收藏和关注!关注我,了解更多 Python 和 NumPy 的实用技巧。

posted @   爱上编程技术  阅读(7)  评论(0编辑  收藏  举报  
相关博文:
阅读排行:
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· 上周热点回顾(2.24-3.2)
点击右上角即可分享
微信分享提示