文件读写以及with语句用法
- 1. 打开文件
- 2. 读取文件
- 2.1 按字节或字符读取
- 2.2 按行读取
- 3. 写文件
- 3.1 按字节或字符写
- 3.2 按行写
- 4. 游标
- 5. with语法
- 5.1 使用with语句打开文件
- 5.2 什么样的对象可以用with语句实例化
1. 打开文件
Python
中提供了一个内置的open()
函数,该函数用于打开指定文件。
open(filename [, access_mode][, buffering][, encoding])
其中access_mode
表示文件打开模式,共有如下几种:
模式 | 作用 |
r | 只读模式 |
w | 写模式 |
a | 追加模式 |
+ | 读写模式,可与其他模式结合使用,比如r+,w+都代表读写模式。 |
b | 二进制模式,可与其他模式结合使用,比如rb代表二进制只读模式, rb+代表二进制读写模式,ab代表二进制追加模式。 |
以w和w+模式打开文件后,open()
函数会立即清空文件内容,所以使用这两种模式时都无法读取文件内容。
该函数返回一个文件对象,文件对象支持如下常见的属性:
-
file.closed
:该属性返回文件是否已经关闭。 -
file.encoding
:返回文件的编码方式。 -
file.mode
:返回被打开文件的访问模式。 -
file.name
:返回文件的名称。
函数参数中的encoding
表示使用哪种编码方式开打开文件。
2. 读取文件
Python
既可以使用文件对象的方法来读取文件,也可以使用其它模块的函数来读取文件。
2.1 按字节或字符读取
文件对象提供了read()
方法来按字节或字符读取文件内容,到底是读取字节还是字符则取决于文件打开的模式。
当以二进制模式来进行文件读取的时候,使用open()来打开文件时,不需要指定encoding
参数。
fp = open('test.txt', 'rb')
data = fp.read()
print(type(data), data)
fp.close()
#======output=====
<class 'bytes'> b'hahahaha'
在使用read()
方法来读取内容时,返回的也是bytes
类型的数据。
当文件读写完毕之后,最好调用close()
方法来关闭文件这样可以避免文件泄露。
2.2 按行读取
文件对象提供了两个按行读取的方法:
-
readline()
:读取文件中的一行,可以指定多少个字符算一行。 -
readlines()
:读取文件内的所有行,它返回的是一个list,每一行为list中的一个元素。
3. 写文件
3.1 按字节或字符写
文件对象提供了write()
方法来按字节或按字符向文件中写内容,与read()
方法的使用方法相同需要指定文件的打开模式。
fp = open('test.txt', 'w', encoding='utf-8')
fp.write('hahahaha')
fp.close()
这里我们使用w
模式打开文件,默认就是以字符方式进行写操作。
当使用wb
模式来打开文件时,就会以字节方式进行写操作,在write
中传入的字符串必须是bytes
类型。
fp = open('test.txt', 'wb')
fp.write(b'hahahaha')
fp.close()
当然这里的open
方法中也不能指定encoding
参数。
3.2 按行写
文件对象提供了一个按行写的方法:
-
writelines(lines: List[AnyStr])
:这里需要传入的是一个list,里面的每个元素为行中的内容,但是它不会自动换行,如果元素中不加换行符,则默认都将写在一行,如果需要每个元素后换行,则需要在每个元素后加入换行符。
4. 游标
这里的游标指的是一个位置,它是一个相对位置。在使用r
或w
模式打开文件时,这个游标的位置在文件的开头,也就是0,当以a
模式来打开文件时,游标会在文件的末尾位置。
它以字节为单位进行移动。
我们可以使用seek()
方法来设置游标的位置,它有两个参数,一个为offset
,表示游标的偏移量,一个为whence
,表示给offset参数的偏移参考,表示要从哪个位置开始偏移;0代表从文件开头开始算起,1代表从当前位置开始算起,2代表从文件末尾算起。
如果要知道当前游标的位置,我们可以使用tell()
方法来查看,该方法返回文件游标的位置。
fp = open('test.txt', 'w', encoding='utf-8')
fp.write('hahahaha')
print(fp.tell())
fp.seek(2)
fp.write('gaigaigai')
print(fp.tell())
fp.close()
#=====output=====
8
11
例如我们先写入hahahaha
,这时游标的位置为8,此时,我们将游标设置到2,然后继续进行写入操作,写入之后的游标位置为11。
这时打开文件我们可以看到,前面写的部分已经被覆盖掉了,剩下的内容为hagaigaigai
。
当我们使用读模式打开时,利用seek()
方法就可以完成部分重复读的操作了。
5. with语法
5.1 使用with语句打开文件
使用with
语句可以避免文件忘记关闭的情况,省去了手动close()
文件。
with open("test.txt", 'r', encoding='utf-8') as f:
lines = f.readlines()
#其它处理语句
5.2 什么样的对象可以用with语句实例化
要让一个类可以用with语句打开,那么这个类必须实现__enter__
方法和__exit__
方法。例如:
class Test:
def __enter__(self):
print('enter 方法被调用')
def __exit__(self, exc_type, exc_val, exc_tb):
print("exit 方法被调用")
print("exc_type :%s" % exc_type)
print("exc_val :%s" % exc_val)
print("exc_tb :%s" % exc_tb)
这样我们就可以使用with语句来实例化它:
with Test() as t:
print(t)
#====output====
enter 方法被调用
None
exit 方法被调用
exc_type :None
exc_val :None
exc_tb :None
我们可以看到,在一开始会调用__enter__
方法,在with块结束后会调用__exit__
方法,如果with块中的语句出现异常,也会调用__exit__
方法。
再回到with open("test.txt", 'r', encoding='utf-8') as f:
这个语句,使用该语句后,我们不需要手动关闭文件就是因为__exit__
方法,在该方法中它实现了文件的关闭操作,所以我们不用单独使用close()
语句来关闭文件对象。