【问题标题】:File.read() is jumping to weird address in pythonFile.read() 在 python 中跳转到奇怪的地址
【发布时间】:2017-03-27 22:32:40
【问题描述】:

下面的代码

fd = open(r"C:\folder1\file.acc", 'r')
fd.seek(12672)
print str(fd.read(1))
print "after", fd.tell()

返回 after 16257 而不是预期的 after 12673

这里发生了什么?文件的创建者有没有办法对文件进行某种保护以干扰我的读取?我只遇到一系列地址的问题。文件的其余部分按预期读取。

【问题讨论】:

  • 您可能已到达文件末尾。
  • 为什么当我在完全没有错误检查的情况下做这些事情时,它会表现得很奇怪?
  • 我还没有到达文件末尾。
  • @KenWhite id 当然愿意向您展示我应该如何错误检查。
  • 使用像C:\... 这样的路径名,您显然使用的是Windows。您还使用'r' 而不是'rb' 打开了文件,因此您已经以“文本模式”打开了它。因此,我不会对奇怪的文件偏移量感到惊讶,但由于我不使用 Windows,我不敢尝试解释这组 特定 值。

标签: python file binaryfiles


【解决方案1】:

看起来您正在尝试使用简单的“线性增加偏移量的字节流”模型处理文件,但您使用'r' 而不是'rb' 打开它。鉴于路径名以C:\ 开头,我们还可以假设您在 Windows 系统上运行。 Windows 上的 Text 流——无论是在 Python 中打开,还是在包括 CPython 的 C 基础在内的各种其他语言中打开——进行有趣的翻译,其中 Python 中的 '\n' 变成字节内的两字节序列 '\r', '\n' -作为存储在文件中。这使得文件偏移以非线性方式表现(尽管作为避免使用 Windows 的人,我不想猜测精确的行为)。

因此,以'rb' 模式打开文件文件进行阅读很重要。当您使用 Python3 时,这一点变得更加重要,它使用 Unicode 作为基本字符串:以'r' 模式打开一个流会产生 text,就像在字符串中一样,type 'str',它们是 Unicode;但以 'rb' 模式打开它会产生 bytes,就像在 <class 'bytes'> 的字符串中一样。

关于你没有问到的事情的注释

如果您不想截断现有文件,可以使用r+b 进行写入,或者使用wb 创建新文件或截断任何现有文件。请记住,+ 表示“添加其他模式”,而 w 表示“截断现有或重新创建以进行写入”,因此r+ 是不截断的读写,而w+ 是写和-用 截断读取。在所有情况下,包括b 都意味着“......并视为字节流。”

如您所见,这里缺少一个模式:如何打开以写入(仅)没有截断,但在必要时创建文件? Python 和 C 一样,为您提供第三个字母选项 a(您也可以像往常一样将其与 +b 混合使用)。这会在不截断的情况下打开写入,仅在必要时创建一个新文件——但它有一些令人讨厌的副作用,即强制 all 写入追加,这就是 a 所代表的。这意味着您无法在不截断的情况下打开文件进行写入,将其定位到文件的中间,并仅覆盖其中的一部分。相反,您必须打开读加,定位到它的中间,然后只覆盖一位。但如果文件当前不存在,则 read-plus 模式会失败 - 引发 OSError 异常。

您可以使用r+ 打开,如果失败,请使用ww+ 重试,但这里的缺陷是操作是非原子的: 如果两个或多个实体——我们称他们为 Alice 和 Bob,尽管它们通常只是两个相互竞争的程序——试图在单个文件名上执行此操作,Alice 可能会看到该文件尚不存在,然后暂停了一下;然后 Bob 看到该文件不存在,创建并截断它,写入内容并关闭它;然后 Alice 恢复并创建和截断,丢失 Bob 的数据。 (实际上,像这样的两个竞争实体无论如何都需要合作,但要可靠地合作,它们需要某种原子同步,为此您必须放弃特定于操作系统的操作。Python 3.3 为 x 字符em>exclusive,这有助于实现原子性。)

如果您确实打开了一个读写流,还有另一个烦人的警告:任何时候你想“切换方向”you are required to introduce an apparently-pointless seek。 (“任何时候”有点太强了:例如,在尝试读取产生文件结尾之后,您也可以切换。然而,要记住的一组条件有点困难;说“更容易”在改变方向之前先寻找。”)这是从底层 C“标准 I/O”实现继承的。 Python 可以解决这个问题——我刚才正在寻找 Python 3 是否可以,但没有找到答案——但 Python 2 没有。底层的 C 实现也不需要有这个缺陷,有些,比如我的,没有,但最安全的假设是它可能,并进行明显毫无意义的搜索。

【讨论】:

    猜你喜欢
    • 2018-10-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-10-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多