打开文件

    在读写文件之前首先需要“打开”文件,这个步骤可以简单地理解为对磁盘文件进行必 要的初始化,至于其底层细节则无需了解。

    Python 提供了函数 open 用于文件打开,用法如下:

    其含义是按指定的<打开方式>打开由<文件名>标识的磁盘文件,创建一个文件对象作为函 数的返回值,并使变量 f 引用这个文件对象。常用的打开方式包括”r”和”w”,它们分别表示 “读”方式和“写”方式。

    顺便强调一下,Python 中的文件处理是面向对象风格的,即文件是一个对象,通过文 件对象的方法来实现文件操作。我们在第 5 章中初步介绍了对象概念,并且将在第 7 章详细 讨论面向对象。

    为了读取一个文件的内容,需要以读方式打开文件。例如:

    成功执行后,就可以通过文件对象 f 来读取文件 oldfile.dat 的内容了。若指定的文件不存在, 则 Python 将报错(IOError)。

    为了向一个文件中写入内容,需要以写方式打开文件。例如:

    1. f = open("newfile.txt","w")

    成功执行后,就可以通过文件对象 f 来向文件 oldfile.dat 中写入内容了。注意,以写方式打 开文件时,如果指定的文件不存在,则创建该文件;如果指定的文件已经存在,则会清除该 文件原来的内容,即相当于创建新文件。所以,以写方式打开文件时一定要小心,不要把现 有文件破坏了。

    读文件

    在介绍文件读写之前,先要理解文件“当前读写位置”的概念。读者应该了解老式的录 放机的录放过程吧:录放机有一个磁头,用于读取或录入磁带信息,随着磁带的转动,磁头 也就不断改变着录放位置。Python 中的文件采用类似的顺序读写过程:打开文件后,当前 读写位置就是文件开始处;随着读写命令的执行,当前读写位置不断改变,直至到达文件末 尾。

    Python 中的文件对象提供了 read()、readline()和 readlines()方法用于读取文件内容。 read()的用法如下:

    1. <变量> = <文件对象>.read()

    含义是读取从当前位置直到文件末尾的内容,并作为字符串返回。如果是刚打开的文件对象, 则返回的字符串包含文件的所有内容。

    read()方法也可以带有参数:

    1. <变量> = <文件对象>.read(n)

    假设有一个文件 rhyme.txt,其文本内容是:

    1. Good, better, best, Never let it rest, Till good is better, And better, best.

    下面的语句序列对此文件进行读取

    readline()的用法如下:

    1. <变量> = <文件对象>.readline()

    含义是读取从当前位置到行末(即下一个换行字符)的所有字符,并以此字符串作为返回值, 赋值给变量。通常用此方法来读取文件的当前行。如果当前处于文件末尾,则 readline 返回 空串。例如:

    1. >>> f = open("rhyme.txt","r")
    2. >>> s = f.readline()
    3. >>> s
    4. 'Good, better, best,\n'
    5. >>> f.readline()
    6. 'Never let it rest,\n'
    7. >>> print f.readline()
    8. Till good is better,
    9. >>> f.close()

    readlines()的用法如下:

    1. <变量> = <文件对象>.readlines()

    其含义是读取从当前位置直到文件末尾的所有行,并将这些行构成一个字符串列表作为返回 值,列表中的每个元素都是文件的一行。如果当前处于文件末尾,则 readlines 返回空列表。 例如:

    1. >>> f = open("rhyme.txt","r")
    2. >>> f.readline()
    3. >>> f.readline()
    4. 'Never let it rest,\n'
    5. >>> f.readlines()
    6. ['Till good is better,\n', 'And better, best.\n']
    7. >>> f.readlines()
    8. []

    写文件

    当文件以写方式打开时,可以向文件中写入文本内容。与读文件一样,写入位置也是由 “当前读写位置”决定的。Python 文件对象提供两种写文件的方法:

    1. <文件对象>.write(<字符串>)
    2. <文件对象>.writelines(<字符串列表>)

    其中,write 的含义是在文件当前位置处写入字符串,writelines 的含义是在文件当前位置处依次写入列表中的所有字符串。 下面的语句序列创建了一个新文件,并向其中写入了李白的名诗:

    注意每一次 f.write()都是紧接着上次写入的内容继续的,并不会因为是另一条 f.write()就另 起一行。为了写多行文本,必须人工添加换行字符“\n”。那么,上述语句序列所创建的文 件 libai.txt 有几行文本呢?没错,只有 3 行,因为第一次调用 f.write 时并没有写入换行符, 这导致诗的前两句被写在同一行上了。如图 6.2 所示。

    图 6.2 写入多行文本

    再次强调,写方式打开文件会导致要么创建一个新文件,要么清除一个旧文件,总之文件的内容是全新的。那么有没有办法在现有文件内容基础上再写入一些新内容呢?答案是肯 定的。Python 还提供一种文件打开方式”a”,表示“追加”。以追加方式打开文件后,当前位 置被定位在文件末尾,可以继续写入文本而不改变原有的文件内容。例如:

    1. >>> f = open("d:/libai.txt","a")
    2. >>> f.write("\n---- 李白《静夜思》")
    3. >>> f.close()

    结果如图 6.3 所示。

    图 6.3 向文件追加写入内容

    关闭文件

    文件处理结束后需要关闭文件,这个步骤大体上涉及释放分配给文件的系统资源,以便 分配给其他文件使用。通过调用文件对象的 close 方法来关闭文件:

    1. <文件对象>.close()

    注意,即使程序中没有关闭文件,Python 程序结束时也会自动关闭所有打开的文件。

    然而好的做法是由程序自己关闭文件,否则有可能因程序意外终止而导致文件数据丢失。例 如,以写方式打开文件时,如果向文件中写入了文本但还没有关闭文件,那么所写内容是不 会存盘的。这时再以读方式打开同一文件,read()命令返回的是空串。下面的语句序列演示 了这种情况。

    1. >>> f = open("d:/test","w")
    2. >>> f.write("some words")
    3. >>> g = open("d:/test","r")
    4. >>> g.read()
    5. ''
    6. >>> g.read()
    7. 'some words'

    所以,强烈建议读者在程序中一旦结束对文件的读写,就立即关闭文件。

    文件处理程序的常见结构

    许多应用程序的算法结构都属于直接了当的 IPO(输入-处理-输出)模式,当输入输 出都是文件时,程序的结构大体如下:

    1. infile = open("input.dat","r")
    2. outfile = open("output.dat","w")
    3. while True:
    4. text = infile.readline()
    5. if text == "":
    6. break
    7. do something with text ...
    8. outfile.write(data)
    9. infile.close()
    10. outfile.close()

    此代码的核心是一个 while 循环,循环的每一步利用 readline()读取输入文件的一行,然后对该行进行处理,并将处理结果写入输出文件。当某次循环读到空行(视为文件尾),则利用 break 跳出循环体,从而结束对文件的处理。

    除了“while 循环+readline()”的结构,还可以利用“for 循环+readlines()”的结构。readlines() 一次性读出所有行,形成一个列表,然后针对这个列表进行循环。

    1. for line in infile.readlines():
    2. do something with line
    3. ...

    实际上,Python 语言甚至允许直接将打开的文件与 for 循环结合使用,达到和“for 循 环+readlines()”同样的效果。代码如下:

    这种用法有个好处是无需考虑内存大小,而 readlines()要求内存足够大,以便容纳它返回的 列表。

    向文件追加数据

    前述读方式打开的文件只能读取不能写入,写方式打开的文件是新建文件(写打开现存文件的话将清除内容),只能写入不能读取。有没有办法保留现存文件的内容并加入新内容 呢?

    其实 Python 还提供了一种打开方式”a”,称为“追加”方式,可以用于在现存文件的尾 部追加新数据。当然,如果请求打开的文件不存在,”a”方式就和”w”方式一样,创建一个新 文件。下面的语句演示了追加方式的用法:

    1. >>> f = open("oldfile.txt","a")
    2. >>> f.close()