跳转至

Topic 11.1 - 文件操作的基本方法

1. 文件操作的基本概念

我们常说,程序就是用来处理数据的,但是到目前为止,我们接触到的数据都是直接在程序中定义的,比如变量、列表、字典等。

  • 但是在实际应用中,数据往往是存储在文件中的,比如文本文件、图片文件、音频文件等

  • 程序需要通过读取这些文件来获取数据,或者将处理后的数据写入到文件中进行保存

在Python中,文件的基本操作主要包括以下几个步骤:

  • (1) 打开文件
  • (2) 读取或写入文件
  • (3) 关闭文件:避免文件占用持续资源

2. 文件的读取

(1) 基本的文件读取方法

在Python中,读取文件的基本方法如下:

# 打开文件
file = open("文件路径", "r")

# 读取文件内容
content = file.read()

# 关闭文件
file.close()

这里的"r"表示以只读模式打开文件。

在本节,我们假设我们有一个文本文件,文件名为咏鹅1.txt,内容如下:

咏鹅
唐·骆宾王
鹅,鹅,鹅,
曲项向天歌。
白毛浮绿水,
红掌拨清波。

我们可以使用以下代码来读取这个文件的内容:

# 打开文件
file = open("咏鹅1.txt", "r")

# 读取文件内容
content = file.read()
print(content)
print(type(content)) 

# 关闭文件
file.close()
咏鹅
唐·骆宾王
鹅,鹅,鹅,
曲项向天歌。
白毛浮绿水,
红掌拨清波。
<class 'str'>

可以看到,读取到的内容在 Python 中是一个字符串类型。

(2) 逐行读取文件

有时候,文本文件中的内容如果比较多的话,我们可能不希望一次性读取所有内容,而是逐行读取,这样可以节省内存空间。

逐行读取有两个方法:

  • readline():每次读取一行
  • readlines():一次性读取所有行,返回一个列表,每个元素是一行内容

(a) 使用readline()逐行读取

我们先来看一下 readline() 方法的使用:

# 打开文件
file = open("咏鹅1.txt", "r")

# 逐行读取文件内容
line1 = file.readline()
line2 = file.readline()
print(line1, end='')
print(line2, end='')

# 关闭文件
file.close()
咏鹅
唐·骆宾王

可以看到,readline() 每调用一次,就会读取文件中的一行内容。

如果使用 readline() 来读取所有行,就要使用到循环了:

# 打开文件
file = open("咏鹅1.txt", "r")

# 逐行读取文件内容
while True:
    line = file.readline()
    if not line:
        break
    print(line, end='')

# 关闭文件
file.close()
咏鹅
唐·骆宾王
鹅,鹅,鹅,
曲项向天歌。
白毛浮绿水,
红掌拨清波。

在这段代码中,我们使用一个无限循环来不断调用 readline() 方法

  • 每次循环,readline() 方法读取一行内容并赋值给变量 line
  • 如果读取到文件末尾,readline() 方法会读取到一个空字符串
  • 之前我们讲过,空字符串对应的布尔值为 False,所以此时我们使用 if not line: 来判断是否读取到文件末尾,如果是,则跳出循环
  • 除此之外,我们在打印时使用了 end='',这是因为每行结尾本身就包含了换行符,如果不指定 end='',则会多打印一个换行

(b) 使用readlines()读取所有行

读取所有行还可以使用readlines()方法:

# 打开文件
file = open("咏鹅1.txt", "r")

# 读取所有行
lines = file.readlines()
print(lines)
print(type(lines))

content = ''.join(lines)
print(content)
print(type(content))

# 关闭文件
file.close()
['咏鹅\n', '唐·骆宾王\n', '鹅,鹅,鹅,\n', '曲项向天歌。\n', '白毛浮绿水,\n', '红掌拨清波。']
<class 'list'>
咏鹅
唐·骆宾王
鹅,鹅,鹅,
曲项向天歌。
白毛浮绿水,
红掌拨清波。
<class 'str'>

可以看到,readlines() 方法返回的是一个列表,每个元素是一行内容,包含了结尾的换行符

  • 想要把一个列表的字符串拼接在一起,可以使用字符串的 join() 方法

  • 我们使用 ''.join(lines),表示用空字符串将列表中的每个元素连接起来,形成一个完整的字符串

3. 文件的写入

(1) 基本的文件写入方法

(a) 覆盖式写入

在Python中,写入文件的基本方法如下:

# 打开文件
file = open("文件路径", "w")

# 写入文件内容
file.write("内容")

# 关闭文件
file.close()

这里的 "w" 表示以写入模式打开文件,如果文件存在则覆盖,如果文件不存在则创建。

我们来尝试自己在 Python 中写一遍《咏鹅》,然后把它写入一个新的文本文件 咏鹅2.txt 中:

# 打开文件
file = open("咏鹅2.txt", "w")

content = '''
咏鹅
唐·骆宾王
鹅,鹅,鹅,
曲项向天歌。
白毛浮绿水,
红掌拨清波。
'''.strip()  # 使用 strip() 去除头和尾的多余空行

# 写入文件内容
file.write(content)

# 关闭文件
file.close()

运行这段代码后,会在当前目录下生成一个名为 咏鹅2.txt 的文本文件,我们点开可以看到内容如下:

咏鹅
唐·骆宾王
鹅,鹅,鹅,
曲项向天歌。
白毛浮绿水,
红掌拨清波。

如果我们再以覆盖式写入的方式打开 咏鹅2.txt 文件,并写入新的内容:

# 打开文件
file = open("咏鹅2.txt", "w")

# 写入新的内容
content = "骆宾王在完成《咏鹅》这首诗时,只有七岁。"
file.write(content)

# 关闭文件
file.close()

运行这段代码后,咏鹅2.txt 文件的内容会被新的内容覆盖,变成:

骆宾王在完成《咏鹅》这首诗时,只有七岁。

因此,在使用覆盖式写入时要特别小心,避免误操作导致文件内容丢失。

(b) 追加式写入

一种相对安全的写入方式是追加式写入,这种方式不会覆盖原有内容,而是在文件末尾追加新的内容。

追加式写入的基本方法如下:

# 打开文件
file = open("文件路径", "a")

# 追加文件内容
file.write("内容")

# 关闭文件
file.close()

这里的 "a" 表示以追加模式打开文件,如果文件存在则在末尾追加内容,如果文件不存在则创建。

我们自己在 Python 中写一遍《咏鹅》,来尝试使用追加式写入的方式,先写入到 咏鹅3.txt 文件中:

# 打开文件
file = open("咏鹅3.txt", "a")

content = '''
咏鹅
唐·骆宾王
鹅,鹅,鹅,
曲项向天歌。
白毛浮绿水,
红掌拨清波。
'''.strip()  # 使用 strip() 去除头和尾的多余空行

# 追加文件内容
file.write(content)

# 关闭文件
file.close()

运行这段代码后,会在当前目录下生成一个名为 咏鹅3.txt 的文本文件,我们点开可以看到内容如下:

咏鹅
唐·骆宾王
鹅,鹅,鹅,
曲项向天歌。
白毛浮绿水,
红掌拨清波。

如果我们再以追加式写入的方式打开 咏鹅3.txt 文件,并写入新的内容:

# 打开文件
file = open("咏鹅3.txt", "a")

# 追加新的内容
content = "\n骆宾王在完成《咏鹅》这首诗时,只有七岁。"
file.write(content)

# 关闭文件
file.close()

运行这段代码后,咏鹅2.txt 文件的内容会变成:

咏鹅
唐·骆宾王
鹅,鹅,鹅,
曲项向天歌。
白毛浮绿水,
红掌拨清波。
骆宾王在完成《咏鹅》这首诗时,只有七岁。

可以看到,以追加式写入的方式,原有内容得以保留,并在末尾追加了新的内容。

其实,追加式写入也有一个问题:

  • 那就是如果写入代码运行多次,内容会被多次追加,导致文件内容冗长重复
  • 因此,使用追加写入时,一定要注意控制写入的次数,避免重复写入同样的内容

(2) 逐行写入文件

和读取文件一样,写入文件也可以逐行写入,来避免一次性写入大量内容。

逐行写入可以使用 writelines() 方法,来将一个列表的字符串逐行写入文件,并且既适用于覆盖式写入,也适用于追加式写入:

我们来尝试使用 writelines() 方法,来将《咏鹅》逐行写入到 咏鹅4.txt 文件中:

# 打开文件
file = open("咏鹅4.txt", "w")
lines = ["咏鹅\n", "唐·骆宾王\n", "鹅,鹅,鹅,\n", "曲项向天歌。\n", "白毛浮绿水,\n", "红掌拨清波。\n"]

# 逐行写入文件内容
file.writelines(lines)

# 关闭文件
file.close()

运行这段代码后,会在当前目录下生成一个名为 咏鹅4.txt 的文本文件,我们点开可以看到内容如下:

咏鹅
唐·骆宾王
鹅,鹅,鹅,
曲项向天歌。
白毛浮绿水,
红掌拨清波。

之后我们再尝试用追加式写入的方式,来将新的内容逐行写入到 咏鹅4.txt 文件中:

# 打开文件
file = open("咏鹅4.txt", "a")
lines = ["\n骆宾王在完成《咏鹅》这首诗时,只有七岁。\n", "这首诗是骆宾王在童年时期创作的。\n"]

# 逐行追加文件内容
file.writelines(lines)

# 关闭文件
file.close()

运行这段代码后,咏鹅4.txt 文件的内容会变成:

咏鹅
唐·骆宾王
鹅,鹅,鹅,
曲项向天歌。
白毛浮绿水,
红掌拨清波。
骆宾王在完成《咏鹅》这首诗时,只有七岁。
这首诗是骆宾王在童年时期创作的。

4. 文件的路径

文件的路径是指文件在计算机中的存储位置:

  • 例如 Windows 系统中,我们常说某个文件保存在 C 盘的某个文件夹下的某个子文件中
  • 例如 Mac 系统中,我们常说某个文件保存在用户目录下文稿文件夹的某个子文件夹中

在 Python 中,文件路径有两种表示方式:

  • 绝对路径:从根目录开始,完整描述文件的位置

    • 例如 Windows 系统中,C:\Users\zhangsan\Documents\file.txt
    • 例如 Mac 系统中,~/Users/zhangsan/Documents/file.txt
  • 相对路径:相对于当前工作目录,描述文件的位置

    • 例如 Windows 系统中,当前工作目录是 C:\Users\zhangsan,那么相对路径 Documents\file.txt 就对应绝对路径 C:\Users\zhangsan\Documents\file.txt
    • 例如 Mac 系统中,当前工作目录是 ~/Users/zhangsan,那么相对路径 Documents/file.txt 就对应绝对路径 ~/Users/zhangsan/Documents/file.txt

我们可以用以下比喻来理解文件路径:

  • 绝对路径:如果我们在互联网上向外国朋友介绍这个👇熊猫的位置,我们会说,这个熊猫在"地球上的亚洲的中国的四川省的成都市的锦江区的春熙路"
  • 相对路径:如果两个人已经身处成都市,一个人问另一个人这个熊猫在哪里,那么就直接可以说,这个熊猫在"锦江区的春熙路"

我们之前在演练文件读写的时候,使用的路径是相对路径

  • 事实上在 Python 开发中,绝大多数情况下我们使用的都是相对路径
  • 因为绝对路径会因为不同电脑的目录结构不同而不同,导致代码无法通用:
  • 比方说,我如果在代码中使用绝对路径 ~/Users/zhangsan/Documents/咏鹅.txt,那么其他人如果在自己的电脑上运行这段代码,就会因为路径不同而报错