零基础学习 Python 之文件

读取文件

假设你已经在某个文件夹下建立了 “test.txt” 文件,且里面有一些内容,那你在当前位置输入 Python3,进入到交互模式,而后执行下面的操做:bash

>>> f = open('test.txt')
>>> for line in f:
...    print(line)
... 
My name is Rocky

I love Python
复制代码

这里提醒你们注意一下,若是是在该文件所在的位置启动的 Python 交互模式,那么按照上面的方法 open(‘test.txt’) 打开文件,这意味着 test.txt 是在当前文件夹下的,若是要打开其它文件夹下的文件,要使用相对路径或者绝对路径来表示,从而让 Python 能找到那个文件。ui

看上面的例子,open() 一个文件,即生成了一个对象,把这个对象赋值给变量 f,从而让变量 f 和文件对象之间创建了引用关系,接下来用 for 循环读取文件中的内容,把读到的文件中的每行赋值给变量 line (这里的每行能够看做是对象),从打印的结果看,每一行与你读取的文件的每一行是相同的。this

若是你作完了上述操做,那么请看下面的操做:spa

>>> for line1 in f:
...    print(line1)
... 
>>>
复制代码

你会奇怪的发现,居然什么也没有,是否是出错了?其实并无,由于以前已经读取过一次文件的内容了,而且到了文件的末尾,再重复操做,就要从文章的末尾开始读了,固然就没有什么东西了,在 Python 中并不会认为这是错误。若是你想再次读取的话,请从新 open() 一下文件。设计

建立文件

读文件只是针对文件的操做之一,还有建立文件。指针

在上面读文件的时候,咱们打开的是一个已经存在的文件,那么如何建立一个新文件呢?请看下面的操做:code

>>> new_file = open('new.txt','w')
>>> new_file.write('this is a new file')
18
>>> new_file.close()
复制代码

new_file = open(‘new.txt’,’w’) 意味着在当前的目录下建立了一个名为 new_file 的文件,该文件为 “w” 打开模式。cdn

new_file.write('this is a new file’) 则是向已创建的新文件中写入 “this is a new file”,而且返回的是写入字符串的长度。对象

new_file.close() 则是关闭当前文件,而后将写入的话保存到文件中。blog

由上面的例子咱们能够看出,建立文件咱们一样用的是 open() ,可是多了个 “w” ,这是告诉 Python 用什么模式打开文件。在 Python 中,能够用不少不一样的模式打开文件,请看下图(截图来自菜鸟教程):

在这里插入图片描述
从上图中能够看出,不一样的模式下打开文件能够进行不一样的读写操做,若是什么都不写的话,默认为以只读(r)的方式打开文件。

使用 with 自动关闭文件

在前面的操做中咱们能够看到,在对文件进行写操做以后,要执行关闭文件的操做,执行关闭文件的操做是为了将写入的内容保存到文件中,若是不进行 close() 操做的话,那么新写入的内容将不会被保存。

Python 早就知道会有不少马大哈们会忘记 close()的操做,因此它建立了一种简单的方法,这就是 with,它会实现自动关闭文件,看!Python 是多么的人性化!请看下面的操做:

>>> new_file.close()
>>> with open('new.txt','a') as f:
...     f.write(‘\nwith is good good good.') ... 23 复制代码

在这里 with 实际上是要发起一个语句的,这里兼具了后面我会讲的 try/finally,便可以在遇到异常的时候发出提醒,此处暂时先不讲,等之后我再细说,咱们先学会用 with。

>>> with open('new.txt') as f:
...    print(f.read())
... 
this is a new file
with is good good good.
复制代码

看吧,在 with 中咱们能够放轻松的扔掉 close 了,上面例子中用到的 read() 方法,在明天的文章中我会讲到。

文件的属性

不少时候,咱们须要获取一个文件的有关属性,好比文件的建立日期,修改日期等等,在 Python 中有一个专门针对时间设计的模块 -- time。请看下面的操做:

>>> import time
>>> time.localtime()
time.struct_time(tm_year=2018, tm_mon=7, tm_mday=25, tm_hour=21, tm_min=49, tm_sec=32, tm_wday=2, tm_yday=206, tm_isdst=0)
复制代码

其实还有一种办法能够查看文件的这些属性,就是 os 模块里的 stat,在这里我就是提一嘴,以后讲到 os 模块的时候再仔细说。

读取文件的内容

由于文件的对象是可迭代的,因此可以用open() 打开文件,因此用 for 循环能够将文件的内容读出来。我在前面的文章说过,能够用 dir() 查看文件对象的属性和方法,当你看了之后你会发现有 3 个方法 read / readline / readlines,单单从名称上看,它们应该和读有关系,事实上确实是这样的,可是它们 3 个又有些微的差异。

1.read()

文件对象的 read() 方法,其实完整的写出来实际上是 read( size ),只不过里面的参数能够省略,若是不省略,则读取文件中的 size 个字符并返回一个字符串;若是省略的话,则读取文件对象的字符知道 EOF,EOF == End - of - file。

>>> f = open('new.txt')
>>> f.read(10)
'this is a '
>>> f.read()
'new filewith is good good good.’ 复制代码

若是你是按照上述的例子依次进行操做的,就会在 f.read() 后出现上述的结果,这主要是由于在前面已经 read(12) 了,指针已经移动到了第 12 个字符后面。

2.readline() & readlines()

readline() 就是它表面的意思,逐行读取文件的内容。

>>> f = open('new.txt')
>>> f.readline()
'this is a new filewith is good good good.'
>>> f.readline()
''
复制代码

每次执行 readline() 的时候它只读一行,直到最后一行,若是还执行 readline() 的话,它不会报错,返回的是空字符串。

一样也是有 readline(size) 的,若是给 readline(size) 参数,则读取相应行的 size 个字符,有兴趣的能够本身试一下。

还有一个是 readlines(),它的做用是将文件中各行读出来,放到一个列表中返回。

>>> f = open('test.txt')
>>> f.readlines()
['My name is Rocky\n', 'I love Python’] 复制代码

既然返回的是一个列表,那么就能用 for 循环读取列表元素,再观察一下能够发现,列表中的每一个元素都是文件的一行,而且是字符串。

>>> f = open('test.txt')
>>> for line in f.readlines():
...    print(line)
... 
My name is Rocky

I love Python
复制代码

这个是否是让你以为和上面文件的 for 循环很相似?

>>> f = open('test.txt')
>>> for line in f:
...    print(line)
... 
My name is Rocky

I love Python
复制代码

乍一看两种方式好像没有什么区别,其实这两种方式是不一样的。在 for line in f 中,并无将文件中因此的行都读入内存,而 for line in f.readlines() 中先执行了 f.readlines(),在内存中有一个列表,列表中包含了全部文件的行,这就是两种方式的区别。

大文件的读取

上面的三个读取文件内容的方法 read 和 readlines 都是一次性将所有的内容读入内存,若是文件不是很大的话,这种作法可以保证读取的速度,可是若是文件内容很大,大到差很少内存那么大或者更大的时候,就不能这么作了。可是 Python 早就替你考虑到了,Python 中有一个 fileinput 模块,可使用它来操做。

>>> import fileinput
>>> for line in fileinput.input('test.txt'):
...    print(line,end = '')
... 
My name is Rocky
I love Python
复制代码

由于我没有大的文件,只是为了演示一下这个模块的用法,对于这个模块更多的内容,能够在交互模式下用 dir() 去查看。

seek

不知道你有没有奇怪过在以前的演示中,每次都要作 f = open(‘***’) 相似的操做,不然就会出现下面的状况:

>>> f = open('test.txt')
>>> for line in f:
...    print(line)
... 
My name is Rocky

I love Python
>>> for line in f:
...    print(line)
... 
>>>
复制代码

是否是发现,当咱们第二次循环文件的时候,既没有报错,也没有显示文件的内容,相似的现象在前面的 readline 中也出现过,这是由于读取文件的时候,有指针随着运动,当读取结束时,指针就到了相应的位置。

当指针结束运动时,可使用 tell() 告诉咱们当前指针的位置。

>>> f = open('test.txt')
>>> f.readline()
'My name is Rocky\n'
>>> f.tell()
17
复制代码

如今咱们来看 seek() 的能力,它可以根据偏移量来移动指针。

>>> f.seek(0)
0
复制代码

上面的意思是将指针移动到文件的开始,若是用 f.readline() 读取的话,如今输出的应该是文件的第一行:

>>> f.readline()
'My name is Rocky\n’ 复制代码

其实还能够操纵指针到任何一个位置,请看下面的操做:

>>> f.seek(10)
10
>>> f.tell()
10
复制代码

f.seek(10) 就是将位置定位到从开头算起到第 10 个字符后面,这时候若是使用 readline 的话,读取的是从当前位置到行末的字母。

写在以后

更多内容,欢迎关注公众号「Python空间」,期待和你的交流。

在这里插入图片描述
相关文章
相关标签/搜索