python文件的读写总结

读写文件是最常见的IO操作。Python内置了读写文件的函数,用法和C是兼容的。

读写文件前,我们先必须了解一下,在磁盘上读写文件的功能都是由操作系统提供的,现代操作系统不允许普通的程序直接操作磁盘,所以,读写文件就是请求操作系统打开一个文件对象(通常称为文件描述符),然后,通过操作系统提供的接口从这个文件对象中读取数据(读文件),或者把数据写入这个文件对象(写文件)。

python 文件操作记住1个函数3个方法:(python中一切皆为对象)

open():请求打开文件:

  如果文件存在返回文件的操作对象,

  如果文件不存在,会抛出异常

关于open()的mode参数

'r':读

'w':写

'a':追加

'r+' == r+w(可读可写,文件若不存在就报错(IOError))

'w+' == w+r(可读可写,文件若不存在就创建)

'a+' ==a+r(可追加可写,文件若不存在就创建)

对应的,如果是二进制文件,就都加一个b就好啦:

'rb'  'wb'  'ab'  'rb+'  'wb+'  'ab+'

read方法——读取文件,将文件读取到内存中,可以一次性读取文件所有内容

write方法——将文件内容写入到文件

close方法——关闭文件

准备文档

往事随风 - 齐秦
词:许常德
曲:涂惠元
你的影子无所不在
人的心事像一颗尘埃
落在过去 飘向未来
掉进眼里就流出泪来
曾经沧海无限感慨
有时孤独比拥抱实在
让心春去 让梦秋来
让你离开
舍不得忘
一切都是为爱
没有遗憾 还有我
就让往事随风 都随风 都随风 心随你动
昨天花谢花开 不是梦 不是梦 不是梦

一、读文件

1、打开文件

要以读文件的模式打开一个文件对象,使用Python内置的open()函数,传入文件名和标示符.

首先,我们看下open函数的定义:

1 def open(file: Union[str, bytes, int], mode: str = ..., buffering: int = ..., encoding: Optional[str] = ..., errors: Optional[str] = ..., newline: Optional[str] = ..., closefd: bool = ...) Inferred type: (file: Union[str, bytes, int], mode: str, buffering: int, encoding: Optional[str], errors: Optional[str], newline: Optional[str], closefd: bool) -> IO Open file and return a stream. Raise IOError upon failure. 

在一般情况下,我们打开文件只需要传入文件路径即可,这里我们读取的文件的内容是中文,为了避免乱码,我们在这里指定了编码格式。其他的参数等我们用到的时候,在仔细说明。open函数返回一个表示文件的对象,python会将这个对象存储在我们的变量f中,这样我们就可以方便的操作了。

我先在桌面创建一个名叫test.txt的文本文件:

>>> f =open('C:Users24414Desktop	est.txt','r',encoding='utf-8')//以绝对路径打开文件
  File "<stdin>", line 1
SyntaxError: (unicode error) 'unicodeescape' codec can't decode bytes in position 2-3: truncated UXXXXXXXX escape

出现这个错误的原因是:windows中的路径是反斜杠,然而反斜杠在python中有着转义字符的意义,所以在py文件中写windows文件路径的时候,要特别注意反斜杠的使用。

下面有三种解决方式:

1 >>> f =open('C:\Users\24414\Desktop\test.txt','r',encoding='utf-8')
2 >>>
3 >>> f =open(r'C:Users24414Desktop	est.txt','r',encoding='utf-8')
4 >>>
5 >>> f =open('C:/Users/24414/Desktop/test.txt','r',encoding='utf-8')
6 >>>

标示符'r'表示读,这样,我们就成功地打开了一个文件。

如果文件不存在,open()函数就会抛出一个IOError的错误,并且给出错误码和详细的信息告诉你文件不存在:

1 >>> f =open('C:Users24414Desktop	est1.txt','r',encoding='utf-8')
2   File "<stdin>", line 1
3 SyntaxError: (unicode error) 'unicodeescape' codec can't decode bytes in position 2-3: truncated UXXXXXXXX escape
4 >>>

2、读取文件

2.1 读取整个文件

操作文件的第一步就是得打开要操作的文件,然后进行读取。在python中我们可以使用open函数来打开一个文件,然后使用read方法来读取文件。

示例1,data.txt和我们的文件在同一目录下,所以直接使用名称即可::

如果是其他路径(非程序目录),那么直接使用绝对路径:
我是在window的开发环境,以windows为例,我们在桌面有一个data1.txt文件:我们在将文件打开后,打印一下这个f到底有些什么:

>>> f = open(r'C:Users24414Desktopdata1.txt', 'r',encoding='gbk')
>>> f.read()
'往事随风 - 齐秦
词:许常德
曲:涂惠元
你的影子无所不在
人的心事像一颗尘埃
落在过去 飘向未来
掉进眼里就流出泪来
 曾经沧海无限感慨
有时孤独比拥抱实在
让心春去 让梦秋来
让你离开
舍不得忘
一切都是为爱
没有遗憾 还有我
就让往事随风 都随风 都随风 心随你动
昨天花谢花开 不是梦 不是梦 不是梦'
>>>

print(dir(f))

输出:

['_CHUNK_SIZE', '__class__', '__del__', '__delattr__', '__dict__', '__dir__', '__doc__', '__enter__', '__eq__', '__exit__', '__format__', '__ge__', '__getattribute__', '__getstate__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__iter__', '__le__', '__lt__', '__ne__', '__new__', '__next__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '_checkClosed', '_checkReadable', '_checkSeekable', '_checkWritable', '_finalizing', 'buffer', 'close', 'closed', 'detach', 'encoding', 'errors', 'fileno', 'flush', 'isatty', 'line_buffering', 'mode', 'name', 'newlines', 'read', 'readable', 'readline', 'readlines', 'reconfigure', 'seek', 'seekable', 'tell', 'truncate', 'writable', 'write', 'write_through', 'writelines']
>>>

这些都是和文件操作相关的,在这里不会给大家做仔细说明,只是让大家对这些东西有个印象,等遇到了,我们在说怎么使用。

2.2 逐行读取

上面是读取整个文件内容,接下来我们看下怎么逐行读取文件。
在逐行读取文本的时候,常见的可以使用for循环来读取:

2.2.1 read()

read:如果指定了参数 size,就按照该指定长度从文件中读取内容,否则,就读取全文。被读出来的内容,全部塞到一个字符串里面。这样有好处,就是东西都到内存里面了,随时取用;但如果文件内容太多了,内存会吃不消。注意换行符也为占用一个内存,缺点需要知道光标的位置,以及每一行的大小SIZE。

>>> f = open(r'C:Users24414Desktopdata1.txt', 'r',encoding='gbk')
>>> f.read(10)
'往事随风 - 齐秦
'
>>> f.read(5)
'词:许常德'
>>>

2.2.2 readline()

概述:readline() 方法用于从文件读取整行,包括 " " 字符。从字面意思可以看出,该方法每次读出一行内容。所以读取时占用内存小,比较适合大文件,该方法返回一个字符串对象。如果指定了一个非负数的参数,则返回指定大小的字节数,包括 " " 字符。

 语法

fileObject.readline(); 

参数

  • size -- 从文件中读取的字节数。

返回值

返回从字符串中读取的字节。

 1 >>> f = open(r'C:Users24414Desktopdata1.txt', 'r',encoding='gbk')
 2 >>> while True:
 3 ...     line=f.read()
 4 ...     if not line:#到 EOF,返回空字符串,则终止循环
 5 ...             break
 6 ...     print(line)
 7 ...
 8 往事随风 - 齐秦
 9 词:许常德
10 曲:涂惠元
11 你的影子无所不在
12 人的心事像一颗尘埃
13 落在过去 飘向未来
14 掉进眼里就流出泪来
15 曾经沧海无限感慨
16 有时孤独比拥抱实在
17 让心春去 让梦秋来
18 让你离开
19 舍不得忘
20 一切都是为爱
21 没有遗憾 还有我
22 就让往事随风 都随风 都随风 心随你动
23 昨天花谢花开 不是梦 不是梦 不是梦
24 >>>

 2.2.3 readlines()

概述:readlines() 方法用于读取所有行(直到结束符 EOF)并返回列表,该列表可以由 Python 的 for... in ... 结构进行处理。当文件太大时,内存可能不够用。 如果碰到结束符 EOF 则返回空字符串。

如果碰到结束符 EOF 则返回空字符串。

语法

readlines() 方法语法如下:

fileObject.readlines( );

参数

  • 无。

返回值

返回列表,包含所有的行。

 1 >>> f = open(r'C:Users24414Desktopdata1.txt', 'r',encoding='gbk')
 2 >>> print(f.readlines())
 3 ['往事随风 - 齐秦
', '词:许常德
', '曲:涂惠元
', '你的影子无所不在
', '人的心事像一颗尘埃
', '落在过去 飘向未来
', '掉进眼里就流出泪来
', '曾经沧海无限感慨
', '有时孤独比拥抱实在
', '让心春去 让梦秋来
', '让你离开
', '舍不得忘
', '一切都是为爱
', '没有遗憾 还有我
', '就让往事随风 都随风 都随风 心随你动
', '昨天花谢花开 不是梦 不是梦 不是梦']
 4 >>> for line in f.readlines():
 5 ...     print(line)
 6 ...
 7 >>>
 8 >>>
 9 >>> f = open(r'C:Users24414Desktopdata1.txt', 'r',encoding='gbk')
10 >>> for line in f.readlines():
11 ...     print(line)
12 ...
13 往事随风 - 齐秦
14 
15 词:许常德
16 
17 曲:涂惠元
18 
19 你的影子无所不在
20 
21 人的心事像一颗尘埃
22 
23 落在过去 飘向未来
24 
25 掉进眼里就流出泪来
26 
27 曾经沧海无限感慨
28 
29 有时孤独比拥抱实在
30 
31 让心春去 让梦秋来
32 
33 让你离开
34 
35 舍不得忘
36 
37 一切都是为爱
38 
39 没有遗憾 还有我
40 
41 就让往事随风 都随风 都随风 心随你动
42 
43 昨天花谢花开 不是梦 不是梦 不是梦
44 >>>

 2.3 读取大文件

如果文件太大,就不能用 read() 或者 readlines() 一次性将全部内容读入内存。

方法一、可以使用 while 循环和 readline() 来完成这个任务。

这里不再举例

方法二、使用 fileinput 模块:

 1 >>> import fileinput
 2 >>> for line in fileinput.input(r'C:Users24414Desktopdata1.txt'):
 3 ...     print(line)
 4 ...
 5 往事随风 - 齐秦
 6 
 7 词:许常德
 8 
 9 曲:涂惠元
10 
11 你的影子无所不在
12 
13 人的心事像一颗尘埃
14 ......

第三种方法,直接读取文件句柄,推荐使用这种方法

 1 >>> f = open(r'C:Users24414Desktopdata1.txt', 'r',encoding='gbk')
 2 >>> f
 3 <_io.TextIOWrapper name='C:\Users\24414\Desktop\data1.txt' mode='r' encoding='gbk'>
 4 >>> for line in f:
 5 ...     print(line)
 6 ...
 7 往事随风 - 齐秦
 8 
 9 词:许常德
10 
11 曲:涂惠元
12 
13 你的影子无所不在
14 
15 人的心事像一颗尘埃

之所以能够如此,是因为 file 是可迭代的数据类型,直接用 for 来迭代即可

3、 关闭文件

 最后一步是调用close()方法关闭文件。文件使用完毕后必须关闭,因为文件对象会占用操作系统的资源,并且操作系统同一时间能打开的文件数量也是有限的:

1 f.close()

 每次都要使用完都要关闭文件,很容易忘记,而且每次都这么写实在太繁琐,所以,Python引入了with语句来自动帮我们调用close()方法:

 1 >>> with open(r'C:Users24414Desktopdata1.txt', 'r',encoding='gbk') as f:
 2 ...     for line in f:
 3 ...             print(line.strip())
 4 ...
 5 往事随风 - 齐秦
 6 词:许常德
 7 曲:涂惠元
 8 你的影子无所不在
 9 人的心事像一颗尘埃
10 落在过去 飘向未来
11 掉进眼里就流出泪来
12 曾经沧海无限感慨

 注意:

file-like Object

open()函数返回的这种有个read()方法的对象,在Python中统称为file-like Object。除了file外,还可以是内存的字节流,网络流,自定义流等等。file-like Object不要求从特定类继承,只要写个read()方法就行。

StringIO就是在内存中创建的file-like Object,常用作临时缓冲。

二进制文件

前面讲的默认都是读取文本文件,并且是UTF-8编码的文本文件。要读取二进制文件,比如图片、视频等等,用'rb'模式打开文件即可:

字符编码

要读取非UTF-8编码的文本文件,需要给open()函数传入encoding参数,例如,读取GBK编码的文件:

1 >>> f = open('/Users/michael/gbk.txt', 'r', encoding='gbk')
2 >>> f.read()
3 '测试'

遇到有些编码不规范的文件,你可能会遇到UnicodeDecodeError,因为在文本文件中可能夹杂了一些非法编码的字符。遇到这种情况,open()函数还接收一个errors参数,表示如果遇到编码错误后如何处理。最简单的方式是直接忽略:

1 >>> f = open('/Users/michael/gbk.txt', 'r', encoding='gbk', errors='ignore')

二、写文件

写文件和读文件是一样的,唯一区别是调用open()函数时,传入标识符'w'或者'wb'表示写文本文件或写二进制文件

>>> f = open(r'C:Users24414Desktopdata2.txt', 'w',encoding='gbk')
>>> f.write('Hello world!')
12
>>>f.flush()

注意:如果指定路径没有data2.txt文件,它会先创建一个文件。

当我们写文件时,操作系统往往不会立刻把数据写入磁盘,而是放到内存缓存起来,空闲的时候再慢慢写入。如果没有这句代码f.flush(),内容只是被写到了缓冲区,等缓冲区满了,才会将内容写到文件中。有了这句代码就会直接写入到文本中,而不会等待缓冲区满。当然也可以最后,调用f.close()实现相同的功能。没有这一步的后果是数据可能只写了一部分到磁盘,剩下的丢失了。

python文件对象提供了两个“写”方法: write() 和 writelines()。

  • write()方法和read()、readline()方法对应,是将字符串写入到文件中。
1 >>> with open(r'C:Users24414Desktopdata2.txt','w',encoding='gbk') as f:
2 ...     f.write('1
2
3
')
3 ...
4 6
5 >>>

  • writelines()方法和readlines()方法对应,也是针对列表的操作。它接收一个字符串列表作为参数,将他们写入到文件中,换行符不会自动的加入,因此,需要显式的加入换行符。
f1 = open(r'C:Users24414Desktopdata2.txt'
, 'w') 
f1.writelines([
"1", "2", "3"])

# 此时test1.txt的内容为:123
f1
= open(
r'C:Users24414Desktopdata2.txt', 'w')
f1.writelines([
"1 ", "2 ", "3 "])
# 此时test1.txt的内容为: # 1 # 2 # 3

 三、file类的其他方法

3.1 tell()和seek()  注意:这里的位置指的是字节数,而不是字符个数

  tell() seek()
概述 返回文件的当前位置,即文件指针当前位置。 用于移动文件读取指针到指定位置。
语法 fileObject.tell()
fileObject.seek(offset[, whence])
参数
  • offset -- 开始的偏移量,也就是代表需要移动偏移的字节数,如果是负数表示从倒数第几位开始。

  • whence:可选,默认值为 0。给 offset 定义一个参数,表示要从哪个位置开始偏移;0 代表从文件开头开始算起,1 代表从当前位置开始算起,2 代表从文件末尾算起。

返回值 返回文件的当前位置。 如果操作成功,则返回新的文件位置,如果操作失败,则函数返回 -1。

 



 

 1 with open('data', 'r', encoding='utf-8') as f:
 2     print(f.readline().rstrip())
 3     print(f.tell())
 4     print(len('往事随风 - 齐秦
'.encode('utf-8')))
 5     print(f.read(4))
 6     print(f.tell())
 7     f.seek(0)
 8     print(f.readline().rstrip())
 9 输出>>>
10 往事随风 - 齐秦
11 23
12 22
13 词:许常
14 35
15 往事随风 - 齐秦

3.2 File flush()

概述

语法

参数

 
 

返回值

flush() 方法是用来刷新缓冲区的,即将缓冲区中的数据立刻写入文件,同时清空缓冲区,不需要是被动的等待输出缓冲区写入。

一般情况下,文件关闭后会自动刷新缓冲区,但有时你需要在关闭前刷新它,这时就可以使用 flush() 方法。

fileObject.flush();
 
   该方法没有返回值。

 

 

1 import  sys,time
2 for i in range(50):
3     sys.stdout.write('#')
4     sys.stdout.flush()
5     time.sleep(0.5)
6 输出>>>
7 ##################################################

3.3 next()

概述 语法 参数 返回值
Python 3 的内置函数 next() 通过迭代器调用 __next__() 方法返回下一项。 在循环中,next()方法会在每次循环中调用,该方法返回文件的下一行,如果到达结尾(EOF),则触发 StopIteration
next(iterator[,default])
返回文件下一行。

文档内容:

第一行
第二行
第三行
第四行
第五行

 示例:

 1 >>> f=open(r'C:Users24414Desktopdata1.txt','r')
 2 >>> for index in range(5):
 3 ...     line=next(f)
 4 ...     print(index,':',line)
 5 ...
 6 0 : 第一行
 7 
 8 1 : 第二行
 9 
10 2 : 第三行
11 
12 3 : 第四行
13 
14 4 : 第五行
15 >>>

3.4 truncate()

概述

语法

返回值

参数

truncate() 方法用于从文件的首行首字节开始截断,截断文件为 size 个字节,无 size 表示从当前位置截断;截断之后 V 后面的所有字节被删除.
fileObject.truncate( [ size ])
该方法没有返回值。 size -- 可选,如果存在则文件截断为 size 字节。

有坑:根据上述文档说明不带参truncate()函数会截取文件头到当前游标位置的字节。
但是,当文件以文本的形式打开时,进行读操作造成游标改变时,文件不会被截取.同样的操作,当文件以二进制方式打开时,文件才会被截取.原因还未知

 1 f = open("data1", "r+", encoding="utf-8")
 2 print(f.readline())
 3 f.truncate()
 4 f.seek(0)
 5 print(f.read())
 6 输出>>>
 7 第一行
 8 
 9 第一行
10 第二行
11 第三行
12 第四行
13 第五行
1 f = open("data1", "r+", encoding="utf-8")
2 print(f.readline())
3 f.truncate(10)
4 f.seek(0)
5 print(f.read())
6 输出>>>
7 第一行
8 
9 第一行

3.5 不常用的两个操作

fileno() 返回一个整型的文件描述符,可以用于一些底层IO操作上(如,os模块的read方法)
isatty() 判断文件是否被连接到一个虚拟终端,是则返回True,否则返回False
原文地址:https://www.cnblogs.com/weststar/p/11346857.html