为什么Python read(3) 会寻找文件末尾

问题描述 投票:0回答:1

我正在尝试理解Python中的文件IO,使用不同的打开模式,以及读取和写入同一文件对象(只是自学)。

我对以下代码感到惊讶(这只是我的探索):

with open('blah.txt', 'w') as f:

    # create a file with 13 characters
    f.write("hello, world!")


with open('blah.txt', 'r+') as f:

    for i in range(5):

        # write one character
        f.write(str(i))

        # then print current position and next 3 characters
        print(f"{f.tell()}: ", f"{f.read(3)}")


with open('blah.txt', 'r') as f:

    # look at how the file was modified
    print(f.read())

哪个输出:

1:  ell
14:  
15:  
16:  
17:  
0ello, world!1234

正如我所料,第一个字符被

0
覆盖,然后接下来读取的3个字符是
ell
但是我希望将
1
写在
o
中的
hello
上,那么接下来的 3 个字符读作
, w

我正在阅读文档here,但我没有看到它在哪里解释了我观察到的行为。

看起来,无论大小如何,第一次读取都会查找文件末尾。

任何人都可以提供文档中解释这一点的链接吗?

我尝试在此网站上搜索类似的问题,但是虽然有很多与阅读相关的问题,但我发现没有一个提到这种行为。

更新

经过更多探索,并不是第一个

read
寻找文件末尾,而是第二次写入。同样,我不确定为什么,这就是为什么我希望在文档中找到解释这种行为的地方。

这是我对上面代码的更改,表明这不是第一次阅读:

with open('blah.txt', 'w') as f:

    # create a file with 13 characters
    f.write("hello, world!")


with open('blah.txt', 'r+') as f:

    for i in range(3):

        # write one character
        f.write(str(i))

        # then print current position and next 3 characters
        print(f"{f.tell()}: ", f"{f.read(3)}")
        print(f"{f.tell()}: ", f"{f.read(3)}")


with open('blah.txt', 'r') as f:

    # look at how the file was modified
    print(f.read())

哪个输出:

1:  ell
4:  o, 
14:  
14:  
15:  
15:  
0ello, world!12```
python io
1个回答
0
投票

考虑这个例子:

with open('test.txt', 'w') as f:
    f.write('HelloEmpty')

with open('test.txt', 'r+') as f:
    print(f.read(5))
    print(f.write('World'))
    f.flush()
    f.seek(0)
    print(f.read(10))

您可能希望打印:

Hello
5
HelloWorld

相反,它打印:

Hello
5
HelloEmpty

即使这段代码:

with open('test.txt', 'w') as f:
    f.write('HelloEmpty')

with open('test.txt', 'r+') as f:
    print(f.read(5))
    print(f.read(5))

按预期工作并打印:

Hello
Empty

因此,

.read()
不会将指针定位在文件末尾,否则第二个打印语句应该会导致错误或出现空值。

但是,请考虑这个例子:

with open('test.txt', 'w') as f:
    for _ in range(10000):
        f.write('HelloEmpty')

with open('test.txt', 'r+') as f:
    print(f.read(5))
    print(f.write('World'))

如果你执行这段代码,然后查看该文件,你会发现在位置8193处,写入了“World”一词。

因此,Python 似乎以 8192 字节或字符块的形式读取文本数据,尽管对

.read()
的连续调用跟踪读取缓冲区中的位置,但对
.write()
的调用将使用已移动的实际文件指针提前 8k(或到文件末尾,以先到者为准)。

无论是字符还是字节,从这里就可以看出:

with open('test.txt', 'w', encoding='utf16') as f:
    for _ in range(10000):
        f.write('HelloEmpty')

with open('test.txt', 'r+', encoding='utf16') as f:
    print(f.read(5))
    print(f.write('World'))

现在,文件中的字符大小为 2 个字节,单词“world”写入位置 4097,因此缓冲区大小以字节为单位。

(请注意,8192 和 4096 是 2 的幂,以防这些数字看起来任意)

© www.soinside.com 2019 - 2024. All rights reserved.