在python中读取一个文本文件相信大家都比较熟悉了,但如果我们遇到一个二进制文件要读取怎么办呢?我们尝试使用 Python 中的内置 open 函数使用默认读取模式读取 zip 文件,抱歉,我们将收到错误消息:

>>> with open("exercises.zip") as zip_file:
...     contents = zip_file.read()
...
Traceback (most recent call last):
  File "<stdin>", line 2, in <module>
  File "/usr/lib/python3.10/codecs.py", line 322, in de
code
    (result, consumed) = self._buffer_decode(data, self.errors, final)
UnicodeDecodeError: 'utf-8' codec can't decode byte 0x8e in position 11: invalid sta
rt byte

我们收到一个错误,是因为 zip 文件不是文本文件,它们是二进制文件。

要从二进制文件中读取,我们需要使用模式 rb 而不是默认模式 rt 打开它:

>>> with open("exercises.zip", mode="rb") as zip_file:
...     contents = zip_file.read()

当从二进制文件中读取时,我们不会得到字符串。将返回一个字节对象,也称为字节字符串:

>>> with open("exercises.zip", mode="rb") as zip_file:
...     contents = zip_file.read()
...
>>> type(contents)
<class 'bytes'>
>>> contents[:20]
b'PK\x03\x04\n\x00\x00\x00\x00\x00Y\x8e\x84T\x00\x00\x00\x00\x00\x00'

字节字符串中没有字符:它们中有字节。

除非我们理解它们的含义,否则文件中的字节对我们没有多大帮助。

使用库来读取二进制文件

处理二进制文件时,你通常会使用和知道如何处理正在使用的特定类型文件的库(内置 Python 库或第三方库)。该库将完成将文件中的字节解码为更易于使用的工作。

例如,Python 的 ZipFile 模块可以帮助我们读取 zip 文件中的数据:

>>> from zipfile import ZipFile
>>>
>>> with ZipFile("exercises.zip") as zip_file:
...     test_file = zip_file.read("exercises/test.py").decode("utf-8")
...
>>> test_file[:30]
'#!/usr/bin/env python3\nfrom __'

如果有人已经完成了这项工作,最好避免实现自己的字节检查或字节操作逻辑。

在 Python 中以字节级别工作

有时你会使用或被要求直接在字节级别工作的库或 API。在这种情况下,你需要至少需要对二进制文件和字节字符串有一点了解。

例如,假设我们要计算给定文件的 sha256 校验和。

在这里,我们有一个名为 get_sha256_hash 的函数来执行此操作:

import hashlib
def get_sha256_hash(filename):
    with open(filename, mode="rb") as f:
        return hashlib.sha256(f.read()).hexdigest()

此函数读取此文件中的所有二进制数据。我们正在读取字节,因为 Python 的 hashlib 模块要求我们使用字节。hashlib 模块在底层工作:它使用字节而不是字符串。

因此,我们传入文件中的所有字节以获取哈希对象,然后对该哈希对象调用 hexdigest 方法以获取表示该文件的 SHA-256 校验和的十六进制字符串:

>>> get_sha256_hash("exercises.zip")
'9e98242a21760945ec815668fc79d8621fa15dd23659ea29be2c5949153fe96d'

此功能运行良好,但使用此功能读取非常大的文件可能会出现问题。

分块读取二进制文件

我们的 get_sha256_hash 函数一次将整个文件读入内存。一个非常大的文件可能会占用大量内存。

对于文本文件,解决此问题的常用方法是逐行读取文件。但是二进制文件不一定有行!但是,我们可以尝试逐块读取。

首先,我们将从文件中读取一个 8 KB 的块:

import hashlib
def get_sha256_hash(filename, buffer_size=2**10*8):
    file_hash = hashlib.sha256()
    with open(filename, mode="rb") as f:
        chunk = f.read(buffer_size)

我们首先创建一个新的哈希对象,然后读取一个 8 KB 的块(通过将字节数传递给我们的文件对象的 read 方法)。

现在我们需要文件的其余部分。所以我们将循环:

import hashlib
def get_sha256_hash(filename, buffer_size=2**10*8):
    file_hash = hashlib.sha256()
    with open(filename, mode="rb") as f:
        chunk = f.read(buffer_size)
        while chunk:
            file_hash.update(chunk)
            chunk = f.read(buffer_size)
    return file_hash.hexdigest()

我们重复读取一个块,更新我们的哈希对象,然后读取另一个块。

只要我们不在文件的末尾,我们就会在读取时返回一个真实的块。

但是当我们在文件的最后读取时,我们会得到一个空字节字符串。空字节字符串(如空字符串)是错误的,因此在文件末尾我们将跳出循环。然后我们将像以前一样返回十六进制摘要。

>>> get_sha256_hash("exercises.zip")
'9e98242a21760945ec815668fc79d8621fa15dd23659ea29be2c5949153fe96d'

但是,我们现在不是将整个文件读入内存,而是逐块读取文件。

使用赋值表达式

在逐块读取文件时,通常会看到使用的赋值表达式(通过 Python 的海象运算符):

import hashlib
def get_sha256_hash(filename, buffer_size=2**10*8):
    file_hash = hashlib.sha256()
    with open(filename, mode="rb") as f:
        while chunk := f.read(buffer_size):
            file_hash.update(chunk)
    return file_hash.hexdigest()

在 while 循环中重复读取数据是赋值表达式的一个很好的用例。它可能看起来有点奇怪,但它确实为我们节省了几行代码。

注意:海象运算符是在 Python 3.8 中添加的。

最后总结下,当你在 Python 中读取二进制文件时,你会得到字节,当你读取一个大型二进制文件时,你需要逐块读取它,当然如果可以最好避免自己读取二进制文件,有第三方库可以使用第三方库来处理。

利用Python中的内置open函数读取二进制文件的更多相关文章

  1. ios – 伞框架

    错误.应用程序,通常位于…错误仍然存在你也可以在这里添加(子)框架的路径.

  2. 如何在xcode 6中构建32位和64位的单二进制文件

    我已经遵循this堆栈溢出解决方案,但即使我得到低于警告.我已经选择虽然我得到了警告.请帮帮我.谢谢.解决方法有同样的问题.看起来将’arm64’添加到ValidArchitectures解决了它.

  3. ios – 将二进制文件上传到Apple的iTunesConnect时会发生什么?

    我问,因为:它可能指向我们可以做的事情来加快这个过程.大约一年前,这个过程从“缓慢,因为苹果的服务器功率不足”变得“非常缓慢,因为苹果公司使用的带宽是发送二进制文件所需带宽的3倍”.例如我最近提交了一个90Mb应用程序,Xcode4将超过350Mb的数据上传到Apple.例如刚才我提交了一个8Mb的二进制文件,Xcode4将超过40Mb的数据上传到Apple.最近上传者有了很大的改进.但我想知道:苹果在上传期间实际上做了什么?

  4. XCode 3.2 Ruby和Python模板

    在xcode3.2下,我的ObjectiveCPython/Ruby项目仍然可以打开更新和编译,但是你无法创建新项目.鉴于xcode3.2中缺少ruby和python的所有痕迹(即创建项目并添加新的ruby/python文件),是否有一种简单的方法可以再次安装模板?我发现了一些关于将它们复制到某个文件夹的信息,但我似乎无法让它工作,我怀疑文件夹的位置已经改变为3.2.解决方法3.2中的应用程序模板

  5. ios – iTunes Connect警告:“您的二进制文件不支持iPad”

    我刚刚将一个新的二进制文件上传到iTunesConnect,并将其添加到iOS版本的新版本.添加二进制文件并保存更改后,iTunesConnect会显示警告消息:“您的二进制文件不支持iPad,iPad的屏幕截图或应用视频预览将不会显示在AppStore上.”Xcode项目是使用Cordova3CLI生成的;自从应用从Cordova2迁移以来,上传的二进制文件是第一个Cordova3版本.该应用程

  6. ios – 二进制无效,二进制文件缺少体系结构[arm64]

    没有足够的信誉发布图像,请搜索“TimT”作为他的回复.更新:已经修复“是的,最近有一个修复程序应用于服务器,每个人都应该能够再次提交32位应用程序.–由TimT在同一个线程.我再次尝试,一切都很好.

  7. ios – 不能检查CGPoint是否不等于CGPointZero

    我有一个CGPoint在UIView类中声明,在我的viewController中,我尝试检查CGPoint是否不等于CGPointZero,但是我收到这个错误:二进制表达式(‘CGPoint'(又名’structCGPoint’)’和’CGPoint“)这是if语句:错误指向!=和我不知道为什么它给我一个错误.操纵杆是UIView类,CGPoint速度是这样声明的:@property(非原子)C

  8. 通用定制iOS框架使用Xcode 6.4

    我已经使用Xcode6创建了一个自定义的iOS框架.我尝试了许多脚本来使框架通用(用于模拟器和设备).但是它们都不适用于我.请告诉我一种方法来为iOS创建一个自定义的通用框架Xcode6.解决方法要通过终端将两个二进制文件合并成通用二进制文件:首先编译器件二进制,然后分别编译模拟器二进制.找到这两个二进制文件.如果你想检查哪些架构被编译成每个,你可以在终端中运行这个命令:lipo-info/pat

  9. ios – 您的二进制文件专为iPad Pro设计.上传iPad Pro截图以获得更好的App Store体验警告

    在将应用程序提交到应用程序商店进行审核后,我在iTunesConnect中收到了以下警报.我没有看到在iTunesConnect.中上传iPadPro屏幕截图的选项请告诉我这里可以做些什么.解决方法是的,这是苹果方面的错误.我已经提交了我的应用程序此错误,Apple批准了该应用程序.

  10. ios – 可变形和二进制数据之间有什么区别?

    我最近开始研究核心数据,请任何人告诉我可变数据和二进制数据之间的区别.我需要将myClassObject存储在核心数据中.我创建了属性并将其类型定义为二进制数据,但在存储时我收到错误.解决方法使用二进制属性,可以直接读取和写入NSData的实例.使用可转换属性,您可以读取和写入可以转换为NSData的任何类的实例.实际数据存储与二进制属性相同,但是CoreData使用NSValueTransfor

随机推荐

  1. 10 个Python中Pip的使用技巧分享

    众所周知,pip 可以安装、更新、卸载 Python 的第三方库,非常方便。本文小编为大家总结了Python中Pip的使用技巧,需要的可以参考一下

  2. python数学建模之三大模型与十大常用算法详情

    这篇文章主要介绍了python数学建模之三大模型与十大常用算法详情,文章围绕主题展开详细的内容介绍,具有一定的参考价值,感想取得小伙伴可以参考一下

  3. Python爬取奶茶店数据分析哪家最好喝以及性价比

    这篇文章主要介绍了用Python告诉你奶茶哪家最好喝性价比最高,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习吧

  4. 使用pyinstaller打包.exe文件的详细教程

    PyInstaller是一个跨平台的Python应用打包工具,能够把 Python 脚本及其所在的 Python 解释器打包成可执行文件,下面这篇文章主要给大家介绍了关于使用pyinstaller打包.exe文件的相关资料,需要的朋友可以参考下

  5. 基于Python实现射击小游戏的制作

    这篇文章主要介绍了如何利用Python制作一个自己专属的第一人称射击小游戏,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起动手试一试

  6. Python list append方法之给列表追加元素

    这篇文章主要介绍了Python list append方法如何给列表追加元素,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教

  7. Pytest+Request+Allure+Jenkins实现接口自动化

    这篇文章介绍了Pytest+Request+Allure+Jenkins实现接口自动化的方法,文中通过示例代码介绍的非常详细。对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下

  8. 利用python实现简单的情感分析实例教程

    商品评论挖掘、电影推荐、股市预测……情感分析大有用武之地,下面这篇文章主要给大家介绍了关于利用python实现简单的情感分析的相关资料,文中通过示例代码介绍的非常详细,需要的朋友可以参考下

  9. 利用Python上传日志并监控告警的方法详解

    这篇文章将详细为大家介绍如何通过阿里云日志服务搭建一套通过Python上传日志、配置日志告警的监控服务,感兴趣的小伙伴可以了解一下

  10. Pycharm中运行程序在Python console中执行,不是直接Run问题

    这篇文章主要介绍了Pycharm中运行程序在Python console中执行,不是直接Run问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教

返回
顶部