【问题标题】:Does read() function affect the file content?read() 函数会影响文件内容吗?
【发布时间】:2022-01-24 16:45:16
【问题描述】:

我有一个固定格式的 .txt 文件:

Tudo Bom;Static and Ben El Tavori;5:13;
I Gotta Feeling;The Black Eyed Peas;4:05;
Instrumental;Unknown;4:15;
Paradise;Coldplay;4:23;
Where is the love?;The Black Eyed Peas;4:13;

我正在尝试将第三行中的歌曲名称替换为新名称。

我编写了一个名为my_mp4_playlist 的函数,它接受两个参数: 第一个是文件路径(字符串),第二个是新歌名(字符串)。

我正在尝试首先使用read() 函数获取文件内容,然后将文件行循环到第三行并使用";" 分割行。

我的问题是,当我使用read()函数时,没有什么可拆分的,当我不阅读时,拆分工作正常。

代码(尚未完成)如下所示:

def my_mp4_playlist(file_path, new_song):
    with open(file_path, "r+") as f:  # we using r+ for reading and writing and not overriding ALL text in the file
        file_source = f.read()
        third_line_list = []
        for i, line in enumerate(f, 0):
            if i == 2:
                print(line.split(";"))
                third_line_list = line.split(";")
                break    

print 语句的输出什么都没有。 但如果我评论f.read() 行,输出是:

['Instrumental', 'Unknown', '4:15', '\n']

为什么会这样?我想以更一般的方式了解,而不是针对我的问题的具体解决方案。

【问题讨论】:

  • print() 实际上并没有运行,因为f 是空的。 file_source 未使用;你改用f。我假设这只是您的疏忽,但是如果您仍然感到困惑,请 LMK。
  • 嘿,为什么 f 是空的?为什么当我删除 'file_source = f.read()' 行时 f 不为空?

标签: python file split


【解决方案1】:

https://pynative.com/python-file-seek/

在大多数编程语言中读取文件时,文件对象会维护一个“光标”(也称为“指针”)来跟踪文件中已读取的部分以及后续读取请求从何处开始读取。此光标从文件的第一个字节开始,向前移动直到到达文件的末尾。

例如,当您逐行读取文件时,文件对象从光标的当前位置开始,读取该行,然后将光标前进到它刚刚读取的行的末尾。它知道当光标到达文件末尾时停止读取。

所以在您初次调用f.read() 时,您正在读取整个文件,因此光标位于文件末尾。在随后对enumerate (f,0) 的调用中,由于光标位于文件末尾,因此文件中没有可读取的内容,因此有效地跳过了循环。

当你注释掉f.read()时,由于enumerate (f,0)之前你还没有读过文件,所以文件光标停留在文件的开头,所以这就是你注释掉f.read()时循环起作用的原因

如果您需要保留file_source = f.read()file_source 看起来未使用,所以我不确定它的用途),那么您需要在下次读取之前将文件光标重置到文件的开头。您可以使用 f.seek(0) 执行此操作,这会将光标放回文件中的第 0 个字节。

或者,由于文件的全部内容现在都在file_source,您不再需要直接从文件中读取。

【讨论】:

  • 谢谢!我需要 file_source 以供进一步使用(我发布的代码并不是全部)
【解决方案2】:

当您打开文件时,当前读取位置设置为 0。这里的问题是,当您使用 read() 方法读取文件的全部内容后,读取位置移动到文件末尾。 因此,当您尝试在此枚举器中再次读取文件的内容时,就没有什么可读取的了,因为读取的位置已经在文件的末尾。

如果你注释了 read() 方法,那么当枚举器被调用时读取位置仍然是 0,所以有一些东西要读取。

要解决这个问题,您可以在调用枚举器之前使用 seek() 方法重置读取位置并将其设置为位置 0。

f.seek(0)
for i, line in enumerate(f, 0):

您还可以使用枚举器中的 read() 方法读取的整个文件内容,而不是从文件中读取。这甚至是更可取的解决方案,因为您不需要再次从磁盘读取文件,而是重用内存中已经存在的文件。这样的事情应该这样做:

for i, line in enumerate(file_source.splitlines(), 0):

【讨论】:

  • seek(0) 毫无意义,因为 file_source 未被使用。为什么不简单地删除行file_source = f.read()
猜你喜欢
  • 1970-01-01
  • 2017-09-24
  • 2012-09-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-05-30
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多