前言

文件读写可以说是最常用的功能之一,总结一下python内置的读写文件的方法。

打开文件

  • open
def open(file, mode='r', buffering=None, encoding=None, errors=None, newline=None, closefd=True):
pass

参数说明:

  • file:文件路径,可以是相对路径,也可以是绝对路径

  • mode: 文件的读写方式,默认‘r’,只读方式;

  • buffering:设置缓冲策略,0用于二进制文件,1为行缓冲,用于文本模式;默认二进制文件固定大小缓冲,文本文件行缓冲

  • encoding:设置编码,默认utf-8;该参数不能用于二进制模式;

  • errors:设置怎么处理文件的编码异常,默认strict,发生错误抛出异常;设置ignore忽略编码异常,可能导致数据丢失,这个参数不能用于二进制模式;

  • newline:设置换行符,默认换行符为'\n','\r','\r\n',写入文件的时候,所有文本中的上述三种都会转换成'\n'换行符;当设置为''时,也启用默认模式;如果设置其它合法值,则使用其他值,一般不用;

  • closefd=True :设置文件描述符的状态,当为False时,文件关闭但描述符不关闭,但是打开文件时指定了文件名,那么设置False不会起作用。

文件打开方式介绍

r:	以只读方式打开文件。文件的指针将会放在文件的开头。这是默认模式。
w: 打开一个文件只用于写入。如果该文件已存在则将其覆盖。如果该文件不存在,创建新文件。
a: 打开一个文件用于追加。如果该文件已存在,文件指针将会放在文件的结尾。也就是说,新的内容将会被写入到已有内容之后。如果该文件不存在,创建新文件进行写入。
x: 创建一个新文件,将其打开并编写;如果文件已经存在报错;
rb: 以二进制格式打开一个文件用于只读。文件指针将会放在文件的开头。这是默认模式。
wb: 以二进制格式打开一个文件只用于写入。如果该文件已存在则将其覆盖。如果该文件不存在,创建新文件。
ab: 以二进制格式打开一个文件用于追加。如果该文件已存在,文件指针将会放在文件的结尾。也就是说,新的内容将会被写入到已有内容之后。如果该文件不存在,创建新文件进行写入。
r+: 打开一个文件用于读写。文件指针将会放在文件的开头。
w+: 打开一个文件用于读写。如果该文件已存在则将其覆盖。如果该文件不存在,创建新文件。
a+: 打开一个文件用于读写。如果该文件已存在,文件指针将会放在文件的结尾。文件打开时会是追加模式。如果该文件不存在,创建新文件用于读写。
rb+:以二进制格式打开一个文件用于读写。文件指针将会放在文件的开头。
wb+:以二进制格式打开一个文件用于读写。如果该文件已存在则将其覆盖。如果该文件不存在,创建新文件。
ab+:以二进制格式打开一个文件用于追加。如果该文件已存在,文件指针将会放在文件的结尾。如果该文件不存在,创建新文件用于读写。

关闭文件

  • close()
f = open(file)
f.close()

注意:

由于文件每次打开都需要调用Close函数关闭,可以使用上下文管理器管理文件,其会自动在适当的时候关闭文件。

with open(filename) as f:
f.read()

文件普通读写

方法一:read()

with open(filename) as f:
f.read() # 一次性读取全部,在大文件这是不可取的
f.read(5) # 读取5个字节,如果使用UTF-8编码,5表示5个汉字,也表示5个字母。
f.read(6) # 同一个f对象,多次读取时在上一次的基础上继续往下,如果超过则有多少读多少

方法二:readline()

with open(filename) as f:
f.readline() # 按行来读取,每次返回一行,
f.readline() # 多次读取在上一行的基础上往下,换行符也会被读取

方法三:readlines()

with open(filename) as f:
t = f.readlines() # 按行读取全部的内容作为一个列表返回

方法四:直接遍历打开的文件对象,按行读取

with open('./test.txt','r+') as f:
for line in f:
print(line)

方法五:使用linecache模块

import linecache
line = linecache.getline(filename,5) # 读取文件第五行的数据

说明:getline方法主要用来获取特定的行的内容,当多次读取文件不规则行的时候该方法能提高效率,因为其将文件的内容缓存了一份在内存中,不用每次去磁盘读取,减少了IO,但这也意味着当读取很大的文件的时候,内存消耗十分严重,因为getline内部使用了readlines方法;大文件可能造成内存溢出。

  • readable()方法可以用来判断文件是否可读

方法一:write()

with open(filename,'w',encoding='utf-8') as f:
t = f.write('ddd') # 将内容写入,必须是字符串格式,不可以是数字,返回的是字符串的个数,包括了换行符\r\n占两个字符(windows),占一个字符\n(linux)。
t = f.write('aaa') # 多次写入在原来的基础上继续写入

方法二:writelines()

with open(filename,'w',encoding='utf-8') as f:
f.writelines(['aa','bb']) # 该方法自动将列表元素拼接起来写入文件,参数时一个可迭代对象,列表、字典、集合都可以
  • writeable()可以判断打开的文件对象f究竟是可读的还是可写的。

注意的问题

  1. f.write(123):这种是不被允许的,必须转化成二进制或字符串;

  2. open(filename,'rb',encoding='utf-8'):以二进制格式打开文件是不能指定编码的,否则报错

  3. 以二进制格式打开文件,写入的必须是字节文件,同时写入返回的是字节数;以文本模式打开,写入的必须是文本,同时返回的是字符串个数;一个汉字字符串占3个字节。

普通字符串转化为字节文件的方法:

  1. b'123adf':这种方法只能针对数字和字母,默认使用ascii编码,不能转化汉字;

  2. '123adf'.encode('utf-8):可以转化字母和汉字;

  3. bytes('我的',encoding='utf-8'):可以转化字母和汉字,但必须指定编码格式;

文件的定位读写

  • tell():获取文件指针的位置
with open(filename,'r',encoding='utf-8') as f:
f.read(3)
t = f.tell() # 获取指针的位置,返回3,如果读取到换行符,换行符在windows占两个字节
  • seek(offset,from):设置指针的位置

参数

  • offset:偏移量,设置负数表示向前偏移,正数表示向后偏移,一个汉字占3个字节,字母占一个字节
  • from:偏移的方向
0:表示文件开头
1:表示当前位置
2:表示文件末尾
with open(filename,'r',encoding='utf-8') as f:
f.read(3)
a = f.seek(0,0) # 返回指针定位后的实际位置,默认偏移方向从文件开头算起

注意

  • 在文本模式下打开文件,偏移方向只能从文件开头算起,参数from只能为0,这是因为文本模式涉及到编码的问题,以二进制格式打开文件就可以设置不同的方向。

  • 每次打开文件,读操作的指针都是在文件的开头,写操作的指针在文件的末尾,直到文件被关闭;

几个经典的案例

文件同时读写的情况

    with open('test.txt', 'r+') as f:
print(f.tell()) # 当前指针的位置在开头0
a = f.read(3) # 指针到了位置3
print(a)
print(f.tell())
h = f.write('hhh') # 从文件的末尾写入,相当于追加数据
print(h)
c = f.tell() # 指针在文件的末尾
print(c)
print(f.read()) # 读取从位置3到文件原来的末尾的数据
print(f.tell()) # 当前位置在新的文件末尾和c相同
  • 总结:r+模式下,如果同一个文件对象需要读和写,读和写各有一个指针,它们是相互独立的,读写位置各不干扰;但是tell函数获取到的位置优先表示写的位置;即当程序执行时,如果只有读,tell获取的位置是读的位置;如果出现了写,tell获取的位置就一定是写的位置了,无论后面还有没有更多的读操作;同理其他的模式也一样;

文件同时读写存在偏移的情况

with open('test.txt', 'r+') as f:
print(f.tell()) # 当前读指针的位置在开头0,写指针还未初始化
print(f.read(3)) # 读指针到了位置3
print(f.tell()) # 获取到读指针的位置为3
f.seek(0) # 指针偏移到文件的开头,只能影响一个指针
print(f.read(3)) # 读指针到了位置3
h = f.write('gggg') # 增加一个文件描述符,写指针初始化到文件的末尾,写入数据
j = f.tell() # 获取写的位置优先,写指针在文件末尾
print(j)
f.seek(0) # 指针偏移到文件的开头,读文件的数据更新,加入了写入的数据
j = f.tell() # 获取写指针在文件的开头
print(j)
h = f.write('vvvv') # 从文件开头写入数据,覆盖原来的数据
c = f.tell() # 获取写指针在文件的位置4
print(c)
print(f.read(4)) # 读取从位置4往后的4个字符
print(f.tell()) # 读指针在文件8位置
h = f.write('xxx') # 从文件的末尾写入,相当于追加数据
print(f.tell()) # 当前位置在新的文件末尾
print(f.read()) # 从8位置读取所有的数据
  • 总结:
  1. seek()函数只能影响它下面的第一次的读写操作;并且会将上一次写入的数据更新到读缓冲区中;

  2. 在r+模式下,write()总是从文件的末尾写入,除非受seek函数的影响;

  3. write()操作被偏移影响后,其后的read操作的指针会被移到write操作的位置;

文件同时读写存在且存在更新的情况

    with open('test.txt', 'r+') as f:
f.read()
f.seek(2,0) # 定位到到文件的开头往右2的位置
f.truncate() # 将2位置后所有的数据删除
f.write('aaa') # 写入新的数据
  • truncate():动态删除数据,从当前指针删除后面所有的数据

其他方法

  • flush():刷新文件内部缓冲,直接把内部缓冲区的数据立刻写入文件, 而不是被动的等待输出缓冲区写入,一般close()函数时先调用flush(),然后再关闭文件描述符。

  • fileno:返回一个整型的文件描述符,很少用到;

  • isatty():文件是否连接到一个终端的设备;

  • truncate():文件截取,无参数时从当前的指针位置删除后面所有;有参数时从首行首字母截取数据留下来,其余的删除;

参考

python之文件读写详解的更多相关文章

  1. C++文件读写详解(ofstream,ifstream,fstream)

    C++文件读写详解(ofstream,ifstream,fstream) 这里主要是讨论fstream的内容: #include <fstream> ofstream //文件写操作 内存 ...

  2. 【转载】C++文件读写详解(ofstream,ifstream,fstream)

    原文:http://blog.csdn.net/kingstar158/article/details/6859379 在看C++编程思想中,每个练习基本都是使用ofstream,ifstream,f ...

  3. python文件读写详解

    # Python3 open(file, mode='r', buffering=-1, encoding=None, errors=None, newline=None, closefd=True, ...

  4. python开头——文件声明 详解

    一.解释器声明 1.声明方式 linux #!/usr/bin/python windowns #!c:/python27/python.exe 放在首行 2.作用 告诉电脑,要用/usr/bin下面 ...

  5. C++文件读写详解

    http://blog.csdn.net/kingstar158/article/details/6859379/

  6. 【转】C++文件读写详解(ofstream,ifstream,fstream)

    转:http://blog.csdn.net/kingstar158/article/details/6859379 摘要:具体用法,上面链接中,文章写的很详细,讲解ofstream,ifstream ...

  7. python之OS模块详解

    python之OS模块详解 ^_^,步入第二个模块世界----->OS 常见函数列表 os.sep:取代操作系统特定的路径分隔符 os.name:指示你正在使用的工作平台.比如对于Windows ...

  8. Python对Excel操作详解

      Python对Excel操作详解 文档摘要: 本文档主要介绍如何通过python对office excel进行读写操作,使用了xlrd.xlwt和xlutils模块.另外还演示了如何通过Tcl   ...

  9. Python的logging模块详解

          Python的logging模块详解 作者:尹正杰  版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.日志级别 日志级别指的是产生的日志的事件的严重程度. 设置一个级别后,严重程度 ...

随机推荐

  1. ES6字符串

    1.unicode表示法: alert("\u0061"); alert("\uD842\uDFB7"); alert("\u20BB7") ...

  2. 小甲鱼OD学习第2讲

    这次我们的任务是让我们输入任意用户名密码判断正确 我们输入fishc和111111,显示错误 我们猜测这是用GetDlgItemTextW来收集账号密码的输入值 我们找到了两个函数,给这两个函数都下断 ...

  3. JavaScript正则表达式函数总结

    /* 测试环境:Chrome 63.0.3239.132 */ JS中正则对象修饰符可选值为:"i" "g" "m",即忽略大小写 进行全局 ...

  4. WPF字典集合类ObservableDictionary

    WPF最核心的技术优势之一就是数据绑定.数据绑定,可以通过对数据的操作来更新界面. 数据绑定最经常用到的是ObservableCollection<T> 和 Dictionary<T ...

  5. mac攻略(4) -- 使用brew配置php7开发环境(mac+php+apache+mysql+redis)

    [http://www.cnblogs.com/redirect/p/6131751.html] 网上有很多文章都是错误的,因为是copy别人的,作者没有自己亲测,不仅不能给新手提供帮助,还会产生严重 ...

  6. Lua内存分析工具

    最近给公司写了一个lua内存分析工具,可以非常方便的分析出Lua内存泄露问题,有图形化界面操作,方便手机端上传快照等功能 内存分析我是在c语言端写的,也有人写过lua端的分析工具,也蛮好用的,不过lu ...

  7. C++11 标准库也有坑(time-chrono)

    恰巧今天调试程序遇到时间戳问题, 于是又搜了搜关于取时间戳,以及时间戳转字符串的问题, 因为 time()   只能取到秒(win和linux) 想试试看能不能找到 至少可以取到毫秒的, 于是, 就找 ...

  8. Node.js 基础介绍(一)

    Node.js 学习笔记一) 简单介绍--名称 Node.js,平时听到有好几种叫法,node .Node.js.nodejs ,但是比较正式的称呼还是"Node.js",由于它是 ...

  9. DML、DDL、DCL的区别

    DML(data manipulation language): 它们是SELECT.UPDATE.INSERT.DELETE,就象它的名字一样,这4条命令是用来对数据库里的数据进行操作的语言DDL( ...

  10. php 高并发下 秒杀处理思路

    1.用额外的单进程处理一个队列,下单请求放到队列里,一个个处理,就不会有并发的问题了,但是要额外的后台进程以及延迟问题,不予考虑. 2.数据库乐观锁,大致的意思是先查询库存,然后立马将库存+1,然后订 ...